简单工厂其实并不属于23种GOF设计模式之一,该模式是工厂方法模式的弱化(或者说是工厂方法模式的一种特例),由于简单,因此称为简单工厂模式(Simple Factory Pattern),也叫作静态工厂模式。虽然不是"标准"的设计模式(更像是一种编程习惯),但在实际项目中,采用该方法的案例仍是比较多的。java
简单工厂模式没有严格的定义,咱们姑且使用如下描述:git
提供一个建立对象实例的功能,而无须关心其具体实现。被建立实例的类型能够是接口、抽象类,也能够是具体的类编程
public interface Product { void doSomething(); void doAnything(); } 复制代码
public class ConcreteProductA implements Product { @Override public void doSomething() { System.out.println("ConcreteProductA doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductA doAnything"); } } 复制代码
public class ConcreteProductB implements Product { @Override public void doSomething() { System.out.println("ConcreteProductB doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductB doAnything"); } } 复制代码
public class Creator { public static Product createProduct(String type) { Product product = null; switch (type) { case "A": product = new ConcreteProductA(); break; case "B": product = new ConcreteProductB(); break; } return product; } } 复制代码
public class Client { public static void main(String[] args) { Product productA = Creator.createProduct("A"); productA.doSomething(); productA.doAnything(); Product productB = Creator.createProduct("B"); productB.doSomething(); productB.doAnything(); } } 复制代码
工厂类的扩展比较困难,每增长一个产品,就要在工厂中添加相应的分支,对扩展开放的同时对修改也开放了,不符合开闭原则。若是有不少产品,那么工厂方法会显得特别"臃肿",下降可读性且不易维护。设计模式
Define an interface for creating an object,but let subclasses decide which class toinstantiate.Factory Method lets a class defer instantiation to subclasses.markdown
定义一个用于建立对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。框架
public interface Product { void doSomething(); void doAnything(); } 复制代码
public class ConcreteProductA implements Product { @Override public void doSomething() { System.out.println("ConcreteProductA doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductA doAnything"); } } 复制代码
public class ConcreteProductB implements Product { @Override public void doSomething() { System.out.println("ConcreteProductB doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductB doAnything"); } } 复制代码
public interface Creator { Product createProduct(); } 复制代码
public class ConcreteCreatorA implements Creator { @Override public Product createProduct() { return new ConcreteProductA(); } } 复制代码
public class ConcreteCreatorB implements Creator { @Override public Product createProduct() { return new ConcreteProductB(); } } 复制代码
public static void main(String[] args) { Creator creatorA = new ConcreteCreatorA(); Product productA = creatorA.createProduct(); productA.doSomething(); productA.doAnything(); Creator creatorB = new ConcreteCreatorB(); Product productB = creatorB.createProduct(); productB.doSomething(); productB.doAnything(); } 复制代码
良好的封装性,代码结构清晰编辑器
一个对象建立是有条件约束的,如一个调用者须要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就能够了,不用知道建立对象的艰辛过程,下降模块间的耦合。ide
工厂方法模式的扩展性很是优秀oop
在增长产品类的状况下,只要适当地修改具体的工厂类或扩展一个工厂类,就能够完成“拥抱变化”。spa
工厂方法模式是典型的解耦框架
高层模块值须要知道产品的抽象类,其余的实现类都不用关心,符合迪米特法则,我不须要的就不要去交流;也符合依赖倒置原则,只依赖产品类的抽象;固然也符合里氏替换原则,使用产品子类替换产品父类。
每增长一个产品类,就须要增长一个对应的工厂类,增长了额外的开发量。
利用反射机制来解决"每增长一个产品类,就须要增长一个对应的工厂类"的问题
public interface Creator { <T extends Product> T createProduct(Class<T> clazz); } 复制代码
public class ConcreteCreator implements Creator { @Override public <T extends Product> T createProduct(Class<T> clazz) { Product product= null; try { product = (Product) Class.forName(clazz.getName()).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { e.printStackTrace(); } return (T) product; } } 复制代码
public class Client { public static void main(String[] args) { Creator creator = new ConcreteCreator(); Product productA = creator.createProduct(ConcreteProductA.class); productA.doSomething(); productA.doAnything(); Product productB = creator.createProduct(ConcreteProductB.class); productB.doSomething(); productB.doAnything(); } } 复制代码
工厂方法模式是对简单工厂的进一步抽象和解耦。和简单工厂比:
Provide an interface for creating families of related or dependent objects without specifyingtheir concrete classes.
为建立一组相关或相互依赖的对象提供一个接口,并且无须指定它们的具体类。
产品A家族
public interface ProductA { void doSomething(); void doAnything(); } 复制代码
产品B家族
public interface ProductB { void doSomething(); void doAnything(); } 复制代码
产品A家族,产品等级1
public class ConcreteProductA1 implements ProductA { @Override public void doSomething() { System.out.println("ConcreteProductA1 doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductA1 doAnything"); } } 复制代码
产品A家族,产品等级2
public class ConcreteProductA2 implements ProductA { @Override public void doSomething() { System.out.println("ConcreteProductA2 doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductA2 doAnything"); } } 复制代码
产品B家族,产品等级2
public class ConcreteProductB1 implements ProductB { @Override public void doSomething() { System.out.println("ConcreteProductB1 doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductB1 doAnything"); } } 复制代码
产品B家族,产品等级2
public class ConcreteProductB2 implements ProductB { @Override public void doSomething() { System.out.println("ConcreteProductB2 doSomething"); } @Override public void doAnything() { System.out.println("ConcreteProductB2 doAnything"); } } 复制代码
public interface Creator { /** * 建立A产品家族 * @return */ ProductA createProductA(); /** * 建立B产品家族 * @return */ ProductB createProductB(); // ... // 有N个产品族,在抽象工厂类中就应该有N个建立方法 } 复制代码
有N个产品族,在抽象工厂类中就应该有N个建立方法
public class ConcreteCreator1 implements Creator { @Override public ProductA createProductA() { return new ConcreteProductA1(); } @Override public ProductB createProductB() { return new ConcreteProductB1(); } } 复制代码
public class ConcreteCreator2 implements Creator { @Override public ProductA createProductA() { return new ConcreteProductA2(); } @Override public ProductB createProductB() { return new ConcreteProductB2(); } } 复制代码
有M个产品等级,就应该有M个具体工厂实现
public class Client { public static void main(String[] args) { Creator creator1 = new ConcreteCreator1(); ProductA productA1 = creator1.createProductA(); productA1.doSomething(); productA1.doAnything(); ProductB productB1 = creator1.createProductB(); productB1.doSomething(); productB1.doAnything(); Creator creator2 = new ConcreteCreator2(); ProductA productA2 = creator2.createProductA(); productA2.doSomething(); productA2.doAnything(); ProductB productB2 = creator2.createProductB(); productB2.doSomething(); productB2.doAnything(); } } 复制代码
封装性,高层模块不须要关心每一个产品的实现类,不关心对象是如何建立出来的,只要知道工厂类是谁,就能建立出一个须要的对象
一个产品族中的多个对象被设计成一块儿工做时,它能保证客户端始终只使用同一个产品族中的对象,而且很容易交换产品系列
能够定义产品族内的约束,而且这样的约束对高层模块来讲是透明的
抽象工厂模式的最大缺点就是产品族扩展很是困难,以上面的通用代码为例,若是要增长一个产品C,也就是说产品家族由原来的2个增长到3个,抽象工厂类Creator要增长一个方法createProductC(),而后每一个实现类都要修改,违反了开闭原则。
注意是产品族扩展困难,而不是产品等级,若是新增一个产品等级,只需增长一个具体工厂类的实现便可完成扩展
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,经过抽象工厂模式产生须要的对象是一种很是好的解决方式。
工厂方法模式生产一个产品,抽象工厂模式生产多个产品(一系列产品);在编程中,一般表现为一个接口或者抽象类,也就是说,工厂方法模式提供的全部产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不一样的接口或抽象类。
简单工厂、工厂方法、抽象工厂这三种模式是逐步抽象的,后者适用于更为通常的场景,而前者是后者的特例。但它们的目标是异曲同工的,目的都是灵活地建立所需的对象而且对客户端隐藏对象建立细节,三者的扩展性和开发量有所不一样,能够根据实际状况选择合适的模式来代替以new的方式建立对象的过程:
简单工厂适用于产品种类较少,且不须要太多扩展的场景
工厂方法模式做为简单工厂的进一步抽象和补充,更加适用于有不少扩展需求的场景
若是一个产品族都有相同的约束(在有多个业务品种、业务分类时,即:具备产品族&产品等级结构的概念),则可使用抽象工厂模式
例如一个文本编辑器和一个图片处理器,都是软件实体,可是*nix下的文本编辑器和Windows下的文本编辑器虽然功能和界面都相同,可是代码实现是不一样的,图片处理器也有相似状况。也就是具备了共同的约束条件:操做系统类型。因而咱们可使用抽象工厂模式,产生不一样操做系统下的编辑器和图片处理器。
参考文献:《设计模式之禅》、《大话设计模式》