定义
工厂方法模式是类的创建模式,又叫做虚拟构造子(Virtual Constructor)模式,或多态性工厂模式。(这里的多态性,指的是具体工厂是在运行时决定的)。
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
上一篇中,简单工厂模式的缺点是对"开闭原则"支持的不够,因为简单工厂中的工厂类与具体产品耦合,而不是依赖抽象,所以当有新的产品出现时,必须修改工厂类,将必要的逻辑加入到工厂类中。
在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体的创建的工作交给子类。这个核心类成了一个抽象角色,只给出具体工厂子类必须实现的接口,和具体产品是解耦的。 这种将核心工厂类抽象化的好处是,允许系统在引进新的产品时不需修改工厂类。
结构和角色
抽象工厂(CreatorFactory)角色 : 这个接口(也可以是抽象类)是工厂方法模式的核心。定义具体工厂行为的接口。
具体工厂(ConcreteCreatorFactory)角色 : 这个角色实现抽象工厂,含有与应用相关的逻辑,用于创建具体产品对象。
抽象产品(Product)角色 : 工厂方法模式所创建的对象的超类型,产品对象的共同父类或共同拥有的接口。
具体产品(ConcreteProduct)角色 : 实现抽象产品角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。
package ds.factory.fm; // 抽象产品角色 public interface Product { void operation(); }
package ds.factory.fm; //具体产品A public class ConcreteProductA implements Product { @Override public void operation() { System.out.println("ConcreteProductA operation..."); } }
package ds.factory.fm; //具体产品B public class ConcreteProductB implements Product { @Override public void operation() { System.out.println("ConcreteProductB operation..."); } }
package ds.factory.fm; //抽象工厂角色 负责定义工厂的行为 public abstract class CreatorFactory { abstract Product factory(); }
package ds.factory.fm; //具体工厂角色A 负责创建具体产品(ConcreteProductA) public class ConcreteCreatorFactoryA extends CreatorFactory{ @Override public Product factory() { return new ConcreteProductA(); } }
package ds.factory.fm; //具体工厂角色B 负责创建具体产品(ConcreteProductB) public class ConcreteCreatorFactoryB extends CreatorFactory{ @Override public Product factory() { return new ConcreteProductB(); } }
package ds.factory.fm; public class Client { public static void main(String[] args) { CreatorFactory factoryA = new ConcreteCreatorFactoryA(); Product productA = factoryA.factory(); productA.operation(); CreatorFactory factoryB = new ConcreteCreatorFactoryB(); Product productB = factoryB.factory(); productB.operation(); } }
(为什么要用这么模式?
当有多个地方用到这个产品A,产品B。产品的创建过程很复杂,细节很多,并且产品的创建过程对客户端是隐蔽的,那么将产品的创建封装到工厂是一个很好的做法。
当产品的创建过程发生改变,只需要改一个地方,那就是工厂。如果不采用工厂,所有的客户端都要更改。
如果增加新产品,那么创建新产品类和新产品工厂, 这样不会影响到原来的工厂和客户端。所以如果出现问题就可以直接定位到新的产品。这完全是符合开闭原则的
)
工厂方法模式和简单工厂模式
从结构上来看,区别是很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。
应用
java.io.collection 中iterator()方法接口返还一个具体的Iterator类。
如果只有一个产品使用简单工厂模式。如果只有一个产品族(即只有一个产品接口),这个产品族下面有多个产品时,则使用工厂方法模式。(如果系统需要加入一个新的产品,那么所需要的就是向系统中加入一个这个产品类以及它所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的产品类而言,这个系统完全支持"开闭原则")
工厂方法模式和模板模式
从工厂类的结构上看这两个模式很类似。首先,这两个模式都是基于方法的,工厂方法模式是基于多态性的工厂方法的,而模板方法模式是基于模板方法和基本方法的。其次这两个方法都是将具体工作交给子类。工厂方法模式将创建工作推延给子类,而模板方法模式将剩余逻辑交给子类。