一.  引言

1. 定义

在Java一般通过new操作符产生一个对象实例,new操作符就是用来构造对象实例的。

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。

工厂模式负责将大量共同接口的类实例化,工厂模式可以决定将哪一个类实例化,不必事先知道每次要实例化哪个类

虽然使用工厂模式,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量,提高系统稳定性降低耦合。

所以在一些书籍中工厂模式这样定义:工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

2. 工厂模式的分类(三类)

1)简单工厂模式(Simple Factory) 

2)工厂方法模式(Factory Method) 

3)抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。

GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。

将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。 

二 .  简单工厂模式

1. 定义

简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。

在简单工厂模式中,可以根据自变量的不同返回不同类的实例。

简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。   

2. 组成部分以及优缺点

先来看简单工厂模式的一个例子:

  1.  //抽象产品角色  
  2. public interface Car{  
  3.       public void infomation();  
  4. }  
  5. //具体产品角色  
  6. public class Benz implements Car{  
  7.       public void Infomation() {  
  8.          System.out.println("奔驰车 Made In China");  
  9.       }  
  10. }  
  11. public class Bmw implements Car{  
  12.       public void Infomation() {  
  13.        System.out.println("宝马车 Made In China");  
  14.       }  
  15. }  
  16. //工厂类角色  
  17. public class Factory{
  18.             //工厂方法.注意 返回类型为抽象产品角色  
  19.              public static Car createCar(String type)throws Exception{  
  20.                    Car c = null;
  21.                    try{
  22.                         c = (Car)class.forName(type).newInstance();
  23.                    } catch(Exception e){
  24.                         e.printStackTrace();  
  25.                    }
  26.                    return c;
  27.            }  
  28. }  

 然后客户类使用:

public class  Customer{
public static void main(String[] args) {
Car car= Factory.createCar(benz); // 根据传入的类字节码字符串得到通用接口
car.Infomation();   // 多态性体现,输出"奔驰车 Made In China"
}

①  通过上面的例子可以发现简单工厂模式由三部分组成:

1) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。

2) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 

3) 工厂类角色:这是本模式的核心,被客户端直接调用,根据客户端指定传入的参数,动态创建客户端需要的对象      

② 步骤:

1. 抽象出通用接口,这里是Car接口

2. 对象实现通用接口,这里是benz和Bmw 实现Car接口

3. 创建静态工厂,通过特定参数组,得到通用接口对象

4. 已经得到了通用接口对象,就可以调用具体类类完成同一种功能的同名方法

可以看出,客户端只面对工厂,不用管产品的具体细节,客户只需向工厂要求你需要什么,其他的事情都交给工厂了。

③ 简单工厂模式的优缺点

优点:

1)工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单

工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。

2)客户端无需知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者

的记忆量。  

3)通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点:

1)  由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。  

2)  系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

③ 适用环境

1)工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂

2)客户端只知道传入工厂类的参数,对于如何创建对象不关心

3. 出现的问题

      下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。当客户不再满足现有的车型号的时候,想要另一种新型车,只要这种车符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createCar(String type)方法需要新增case),这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。 
      我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。
      于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。

 

三.  工厂方法模式

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力

可以由工厂方法模式里不同的工厂子类来分担。 

1. 组成部分

由于增加了子工厂分担压力,所以工厂方法模式的组成部分变成了四个部分:

1) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。

2) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 

3) 抽象工厂类角色,这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。

4) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。 

2. 例子分析

  1.  //抽象产品角色  
  2. public interface Car{  
  3.       public void create();  
  4. }  
  5. //具体产品角色  
  6. public class Benz implements Car{  
  7.       public void Infomation() {  
  8.          System.out.println("奔驰车 Made In China");  
  9.       }  
  10. }  
  11. public class Bmw implements Car{  
  12.       public void Infomation() {  
  13.        System.out.println("宝马车 Made In China");  
  14.       }  
  15. }  
  16. //抽象工厂类角色  
  17. public abstact class Factory{
  18.       public Car CreateCar();
  19. }  
  20. //具体工厂角色
  21. public class FactoryBenz extends Factory{
  22.       //Override
  23.       public static benz createCar() {
  24.               return new Benz(); 
  25.       } 
  26. }

客户类只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类的类名:

public class  Customer{
public static void main(String[] args) {
     Factory  FactoryBenz  = new FactoryBenz();
FactoryBenz.createCar()
Benz benz =  factorybenz.createCar();   // 生产出了一个奔驰车
 
}

3. 具体分析

clip_image004

工厂方法被定义为:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象定义;Creator为抽象创建类,也就是抽象工厂,

具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的

4. 优缺点

优点:

① 良好的封装性,代码结构清晰。一个对象创建是有条件约束的,如一个调用者需要一个具体的产品对象,

只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,减少模块间的耦合。

② 工厂方法模式的扩展性非常优秀。在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”。

例如在我们的例子中,需要增加一个大众汽车,则只需要增加一个具体大众汽车类,工厂类不用任何修改就可完成系统扩展。

如果需要增加 衣服制造,就只要多增加一个衣服知道的具体工厂类来分担

四. 抽象工厂模式

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。

比如奔驰系列使用空调型号A和发动机型号A,而宝马系列使用空调型号B和发动机型号B,那么使用抽象工厂模式,

在为汽车生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号。

解析:

当每个抽象产品都有多于一个的具体子类的时候(空调有型号A和B两种,发动机也有型号A和B两种),工厂角色怎么知道实例化哪一个子类呢?

比如每个抽象产品角色都有两个具体产品(产品空调有两个具体产品空调A和空调B)。抽象工厂模式提供两个具体工厂角色(宝马系列工厂和奔驰系列工

厂),分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。

每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例

② 例子

  1. //发动机以及型号    
  2. public interface Engine {    
  3.   
  4. }    
  5. public class EngineA extends Engine{    
  6.     public EngineA(){    
  7.         System.out.println("制造-->EngineA");    
  8.     }    
  9. }    
  10. public class EngineBextends Engine{    
  11.     public EngineB(){    
  12.         System.out.println("制造-->EngineB");    
  13.     }    
  14. }    
  15.   
  16. //空调以及型号    
  17. public interface Aircondition {    
  18.   
  19. }    
  20. public class AirconditionA extends Aircondition{    
  21.     public AirconditionA(){    
  22.         System.out.println("制造-->AirconditionA");    
  23.     }    
  24. }    
  25. public class AirconditionB extends Aircondition{    
  26.     public AirconditionB(){    
  27.         System.out.println("制造-->AirconditionB");    
  28.     }    
  29. }   

创建工厂类:

  1. //创建工厂的接口    
  2. public interface AbstractFactory {    
  3.     //制造发动机  
  4.     public Engine createEngine();  
  5.     //制造空调   
  6.     public Aircondition createAircondition();   
  7. }    
  8.   
  9.   
  10. //为奔驰系列生产配件    
  11. public class FactoryBenz  implements AbstractFactory{    
  12.         
  13.     @Override    
  14.     public Engine createEngine() {      
  15.         return new EngineA();    
  16.     }    
  17.     @Override    
  18.     public Aircondition createAircondition() {    
  19.         return new AirconditionA();    
  20.     }    
  21. }    
  22. }