1.模式描述
工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
当具体的对象过于多时,比如 简单工厂模式 中 当语言种类很多时,使用简单工厂模式 就会显得比较臃肿。因为简单工厂模式只有一个工厂类,它需要处理所有的创建的逻辑。当需求需要创建 n 种语言种类时,那么工厂类则需要n+1
个if-else
来创建不同的类型,后果不堪设想。这个时候就需要使用 工厂方法 模式来实现需求了。在工厂方法模式中,核心的工厂类不再是负责所有的对象的创建,而是将所有的创建工作交给子类去做。此时核心类变成了一个抽象工厂角色,仅仅给出具体工厂子类所必须实现的接口,而不再接触哪一个类应当被实例化这种细节。
2.源代码一
2.1角色
抽象工厂(ExportFactory)角色:担任这个角色的是工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口。在实际的系统中,这个角色也常常使用抽象类实现。
具体工厂(ExportHtmlFactory、ExportPdfFactory)角色:担任这个角色的是实现了抽象工厂接口的具体JAVA类。具体工厂角色含有与业务密切相关的逻辑,并且受到使用者的调用以创建导出类(如:ExportStandardHtmlFile)。
抽象导出(ExportFile)角色:工厂方法模式所创建的对象的超类,也就是所有导出类的共同父类或共同拥有的接口。在实际的系统中,这个角色也常常使用抽象类实现。
具体导出(ExportStandardHtmlFile等)角色:这个角色实现了抽象导出(ExportFile)角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体导出角色的实例。
抽象工厂
public interface ExportFactory {
public ExportFile factory(String type);
}
具体工厂
public class ExportHtmlFactory implements ExportFactory{
@Override
public ExportFile factory(String type) {
// TODO Auto-generated method stub
if("standard".equals(type)){
return new ExportStandardHtmlFile();//产生具体导出对象
}else if("financial".equals(type)){
return new ExportFinancialHtmlFile();//产生具体导出对象
}else{
throw new RuntimeException("没有找到对象");
}
}
}
public class ExportPdfFactory implements ExportFactory {
@Override
public ExportFile factory(String type) {
// TODO Auto-generated method stub
if("standard".equals(type)){
return new ExportStandardPdfFile();//产生具体导出对象
}else if("financial".equals(type)){
return new ExportFinancialPdfFile();
}else{
throw new RuntimeException("没有找到对象");//产生具体导出对象
}
}
}
抽象导出对象
public interface ExportFile {
public boolean export(String data);
}
具体导出对象
public class ExportFinancialHtmlFile implements ExportFile{
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出财务版HTML文件");
return true;
}
}
public class ExportFinancialPdfFile implements ExportFile{
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出财务版PDF文件");
return true;
}
}
public class ExportStandardHtmlFile implements ExportFile{
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出标准HTML文件");
return true;
}
}
public class ExportStandardPdfFile implements ExportFile {
@Override
public boolean export(String data) {
// TODO Auto-generated method stub
/**
* 业务逻辑
*/
System.out.println("导出标准PDF文件");
return true;
}
}
具体调用
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String data = "";
ExportFactory exportFactory = new ExportHtmlFactory();
ExportFile ef = exportFactory.factory("financial");
ef.export(data);
}
}
### 3.源代码二
业务类
class LeiFeng{
public void sweep(){
sysout("sweep");
}
public void wash(){
sysout("wash");
}
}
class Undergraduate : LeiFeng(){}
class Vounteer : LeiFeng(){}
抽象工厂
interface IFactory{
LeiFei createLeiFeng();
}
具体工厂类
class UndergraduateFactory : IFactory{
@override
public LeiFeng createLeiFeng(){
return new Undergraduate();
}
}
class VounteerFactory : IFactory{
@override
public LeiFeng createLeiFeng(){
return new Vounteer();
}
}
调用
IFactory factory = new UndergraduateFactory();
LeiFeng student = factory.createLeiFeng();
student.sweep();
student.wash();
4. 简单工厂模式 VS 工厂方法模式
String type = "chinese";
Say say1 = SayManager.factory(type);
say1.saySomething();
String type = "english";
Say say2 = SayManager.factory(type);
say2.saySomething();
简单工厂模式 中,需要在任何实例化的时候写工厂的代码,这里的重复使代码有了bad smell
。
IFactory factory = new UndergraduateFactory();
//IFactory factory = new VounteerFactory();//只需要更换此处
LeiFeng student = factory.createLeiFeng();
student.sweep();
student.wash();
而在工厂方法模式中只需要在调用时更换抽象工厂的具体类就可以了。
但是工厂方法模式的为每增加一个产品,就需要增加一个产品工厂的类,增加了额外的开发量。