定义
此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。
定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
和简单工厂模式的对比
工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。
具体来说就是,简单工厂是一个可以创建任意对象的超级工厂,而工厂方法定义了一个抽象工厂,不同类型的产品对应不同的工厂实现类,在简单工厂的基础上进一步的抽象。
UML
优点
在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。
在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
缺点
每次增加一种新类型的产品时,都需要增加多个具体类和对象实现工厂,是的系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
应用场景
- 对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
- 只需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。
- 一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。
- 一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。
示例
实现一个创建不同产品的工厂。
Java
1 public class Main 2 { 3 public static void main(String[] args) 4 { 5 //工厂抽象对象 6 Creator factroy; 7 //实例化指定的工厂对象 8 factroy = new ConcreteCreator(); 9 //产品接口 10 IProduct product; 11 //创建指定的产品并使用 12 product = factroy.createProduct(ProductA.class); 13 product.doSomething(); 14 product = factroy.createProduct(ProductB.class); 15 product.doSomething(); 16 } 17 18 /** 19 * 产品接口 20 */ 21 public static interface IProduct 22 { 23 void doSomething(); 24 } 25 26 /** 27 * 产品A 28 */ 29 public static class ProductA implements IProduct 30 { 31 @Override 32 public void doSomething() 33 { 34 System.out.println("ProductA doSomething!"); 35 } 36 } 37 38 /** 39 * 产品B 40 */ 41 public static class ProductB implements IProduct 42 { 43 @Override 44 public void doSomething() 45 { 46 System.out.println("ProductB doSomething!"); 47 } 48 } 49 50 /** 51 * 抽象工厂 52 */ 53 public static abstract class Creator 54 { 55 /** 56 * 这里通过反射得到指定类型的实例, 实际使用中可以根据需求来实现 57 */ 58 public abstract <T extends IProduct> T createProduct(Class<T> c); 59 } 60 61 /** 62 * 具体的工厂实现类 63 */ 64 public static class ConcreteCreator extends Creator 65 { 66 @Override 67 public <T extends IProduct> T createProduct(Class<T> c) 68 { 69 T product = null; 70 try 71 { 72 product = (T) Class.forName(c.getName()).newInstance(); 73 } 74 catch (Exception e) 75 { 76 e.printStackTrace(); 77 } 78 return product; 79 } 80 } 81 }