简单工厂是提供一个工厂负责创建具体实例,如前面第一种方式的话(不是反射的那种方式),如果每增加一种具体产品角色都要修改工厂代码,不符合开闭原则
工厂方法是抽象工厂定义规范,由真实工厂(抽象工厂角色的子类)返回具体的具体产品角色实例 。这样每增加一种具体产品角色只需要增加一个真实工厂,在其对应的真实工厂内返回具体的产品角色实例即可。无须像简单工厂修改工厂代码。
好处是:符合开闭原则,当增加具体产品角色时,只需要增加真实工厂即可
缺点是:增加了类的数量,在客户端调用的时候,需要指定具体的真实工厂获取具体产品角色。
工厂方法四个角色
抽象产品角色(Product):定义产品的接口
具体产品角色(ConcreteProduct) :实现接口Product的具体产品类
抽象工厂角色(Creator) :声明工厂方法(FactoryMethod),返回一个产品
真实的工厂(ConcreteCreator):实现FactoryMethod工厂方法,由客户调用,返回一个产品的实例
这里再提出两个名词:产品族和产品等级
产品等级是相同的属性行为,比如 JavaStudy(). EnglishStudy() ,均属于study行为
产品族是属于同一类别,比如 English语法, English笔记,均属于English分类。
工厂方法是解决产品等级问题。也就是解决相同的属性行为问题
例如demo如下:
定义抽象产品角色(Course),申请行为为study(),代码如下:
public interface Source { public void study(); }
定义具体产品角色JavaSource
public class JavaSource implements Source { public void study() { System.out.println("学习java课程"); } }
定义具体产品角色EnglishSource
public class EnglishSource implements Source { public void study() { System.out.println("学习Enlish source"); } }
定义抽象工厂SourceFactory
public abstract class SourceFatory { /** * 获取课程实例 * @return */ public abstract Source getSource(); }
定义真实工厂EnglishSourceFactory
public class EnlishSourceFactory extends SourceFatory { public Source getSource() { return new EnglishSource(); } }
定义真实工厂JavaSourceFactory
public class JavaSourceFactory extends SourceFatory { public Source getSource() { return new JavaSource(); } }
编写Test测试
public class Test { public static void main(String[] args) { SourceFatory sf = new JavaSourceFactory(); Source source = sf.getSource(); source.study(); SourceFatory sf1 = new EnlishSourceFactory(); Source source1 = sf1.getSource(); source1.study(); } }
当需要具体的某一个产品角色,只需要实例化其对应的具体工厂就可以获取到具体产品实例,且当新增具体产品实例时,只需要增加对应的具体产品实现抽象产品角色,增加具体的产品工厂实现抽象工厂,在具体的产品工厂内返回具体产品角色即可,。
如现在需要一个mathSource的实例:
首先增加具体产品角色 MathSource:
public class MathSource implements Source { public void study() { System.out.println("开始学习了Math 课程。。。"); } }
然后再增加具体的产品工厂 MathSourceFactory :
public class MathSourceFactory extends SourceFatory { public Source getSource() { return new MathSource(); } }
当需要实例的时候只需要实例化具体的工厂就可以获取到具体产品实例
SourceFatory sourceFatory = new MathSourceFactory(); Source source2 = sourceFatory.getSource(); source2.study();
工厂方法解决了同一属性行为的产品等级问题。
产品族问题待下一篇抽象方法模式介绍
对应的UML结构图如下: