工厂方法模式
工厂方法模式是类的创建模式。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工厂推迟到子类中。
工厂方法模式
工厂方法模式是对简单工厂模式进一步抽象的结果。
假如是不使用反射的工厂方法模式,那么所有的if...
else if...else都放在工厂类中,势必造成工厂类的无限臃肿
这时候就需要工厂方法模式来处理这个问题了。工厂方法模式中,核心的工厂类不再负责所有对象的创建,而是将具体的创建工作交给子类去做。这个类则摇身一变变成了一个抽象工厂角色,仅仅负责给出具体工厂子类必须实现的接口。
这一步的改进,使得系统可以在不修改具体工厂角色的情况下引入新的产品。
工厂方法模式结构
使用工厂方法模式的系统涉及到以下角色:
1、抽象工厂角色
担任这个角色的是工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现这个接口
2、具体工厂角色
担任这个角色的是实现了工厂接口的具体Java类,具体工厂角色与业务密切相关,并且随着使用者的调用以创建导出类
3、抽象导出角色
工厂方法模式所创建的对象的超类
4、具体导出角色
这个角色实现了抽象导出角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体角色导出角色的实例
工厂方法模式的示例
有一个抽象工厂,导出文件的工厂:
public interface ExportFactory { public ExportFile factory(String type); }
它有两个实现类,分别是导出HTML文件的工厂和导出PDF文件的工厂:
public class ExportHtmlFactory implements ExportFactory { public ExportFile factory(String type) { if ("standard".equals(type)) { return new ExportStandardHtmlFile(); } else if ("financial".equals(type)) { return new ExportFinancialHtmlFile(); } return null; } }
public class ExportPdfFactory implements ExportFactory { public ExportFile factory(String type) { if ("standard".equals(type)) { return new ExportStandardPdfFile(); } else if ("financial".equals(type)) { return new ExportFinancialPdfFile(); } return null; } }
抽象产品角色,一个导出文件:
public interface ExportFile { public boolean export(String data); }
具体产品角色:
public class ExportFinancialHtmlFile implements ExportFile { public boolean export(String data) { System.out.println("导出财务版HTML文件"); return false; } }
public class ExportFinancialPdfFile implements ExportFile { public boolean export(String data) { System.out.println("导出财务版PDF文件"); return true; } }
public class ExportStandardHtmlFile implements ExportFile { public boolean export(String data) { System.out.println("导出标准HTML文件"); return true; } }
public class ExportStandardPdfFile implements ExportFile { public boolean export(String data) { System.out.println("导出标准PDF文件"); return true; } }
模拟客户端调用,实例化出一个具体的工厂角色,根据传入的参数返回不同的产品角色:
public static void main(String[] args) { String data = ""; ExportFactory exportFactory = new ExportHtmlFactory(); ExportFile ef = exportFactory.factory("financial"); ef.export(data); }
返回结果为:
导出财务版HTML文件
当然,也可以修改代码,看自己喜好,实例化出不同的子类并且调用export方法打印。
工厂方法模式在Java中的应用及解读
拿ThreadFactory举个例子,顾名思义,这是一个生产线程的接口:
public interface ThreadFactory { /** * Constructs a new {@code Thread}. Implementations may also initialize * priority, name, daemon status, {@code ThreadGroup}, etc. * * @param r a runnable to be executed by new thread instance * @return constructed thread, or {@code null} if the request to * create a thread is rejected */ Thread newThread(Runnable r); }
具体的线程工厂可以implements这个接口并实现newThread(Runnable r)方法,来生产具体线程工厂想要生产的线程。JDK在Executors给开发者提供了一个静态内部类DefaultThreadFactory,当然开发者也可以自行实现这个接口,写自定义的线程工厂。
总结
对于系统的设计应该足够灵活并尽可能降低代码之间的耦合度,当修改或增加一个新的功能时,使得使用者尽可能修改少的地方即可。假如设计不够灵活,将无法面对多变的需求,可能一个极小的需求变更,都会使代码结构发生改变,并导致其他使用的人都要修改他们的代码。牵一发而动全身,系统日后的维护将变得艰难。