设计模式之工厂模式

来源:互联网 发布:网络丑男图片 编辑:程序博客网 时间:2024/06/16 06:39

总结

1.使用工厂模式的两种情况:
 1)在编码时不能预见需要创建哪种类的实例。
 2)系统不应依赖于产品类实例如何被创建、组合和表达的细节。

 3)不想让客户代码决定实例化哪个类时。

2.工厂方法模式和抽象工厂模式关系

 1)抽象工厂是工厂方法的集合

 2)抽象工厂模式用来创建“一族”对象,而工厂方法用来创建一个对象。

3.工厂方法模式的意图:定义一个用于创建对象(产品的对象)的接口(工厂类),并控制返回哪个类的实例。让服务的提供者确定实例化哪个类,而不是客户确定。

4.抽象工厂模式又名工具箱,其意图是允许创建一族相关或相互依赖的对象。典型应用GUI控件(工具箱)。

一、引子
      话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)),还雇了司机为他开车。不过,爆发户坐车时总是这样:上Benz车后跟司机说"开奔驰车!",坐上Bmw后他说"开宝马车!",坐上Audi后他说"开奥迪车!"。而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是,这种有病的现象在OO语言中可以避免了。下面以Java语言为基础来引入我们本文的主题:工厂模式!!

二、简介
     工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:
 1. 简单工厂模式(Simple Factory) 
 2. 工厂方法模式(Factory Method) 
 3. 抽象工厂模式(Abstract Factory) 
      这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。

三、简单工厂模式
      顾名思义,这个模式本身很简单,而且使用在业务较简单的情况下。
它由三种角色组成(关系见下面的类图):
1、工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。

2、抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。

3、具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
clip_image002
那么简单工厂模式怎么用呢?下面就来给那个暴发户治病: 
在使用了简单工厂模式后,现在暴发户只需要坐在车里对司机说句:"开车"就可以了。来看看怎么实现的:

//抽象产品角色public interface Car{   public void drive(); } //具体产品角色public class Benz implements Car{   public void drive() {     System.out.println("Driving Benz ");   }  } public class Bmw implements Car{  public void drive() {   System.out.println("Driving Bmw ");  } } 。。。(奥迪我就不写了) //工厂类角色public class Driver{ //工厂方法//注意 返回类型为抽象产品角色public static Car driverCar(String s)throws Exception { //判断逻辑,返回具体的产品角色给Client if(s.equalsIgnoreCase("Benz")) return new Benz(); else if(s.equalsIgnoreCase("Bmw")) return new Bmw(); ...... else throw new Exception(); 。。。 //欢迎暴发户出场...... public class Magnate{  public static void main(String[] args){   try{    //告诉司机我今天坐奔驰   Car car = Driver.driverCar("benz");    //下命令:开车   car.drive(); 。。。 


四、工厂方法模式

先来看下它的组成吧:
1、抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2、具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
3、抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4、具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
来用类图来清晰的表示下的它们之间的关系:

clip_image006

      我们还是老规矩使用一个完整的例子来看看工厂模式各个角色之间是如何来协调的。话说暴发户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是暴发户同情他说:看你跟我这么多年的份上,以后你不用这么辛苦了,我给你分配几个人手,你只管管好他们就行了!于是,工厂方法模式的管理出现了。代码如下:
//抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。

//抽象工厂角色public interface Driver{  public Car driverCar(); } public class BenzDriver implements Driver{  public Car driverCar(){   return new Benz();  } } public class BmwDriver implements Driver{  public Car driverCar() {   return new Bmw();  } } ......//应该和具体产品形成对应关系,这里略... //有请暴发户先生public class Magnate {  public static void main(String[] args)  {   try{    Driver driver = new BenzDriver();    Car car = driver.driverCar();    car.drive();   }catch(Exception e) { }  } } 


      当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族,那么这种情况下就可能可以使用抽象工厂模式了。

五、小结
      让我们来看看简单工厂模式、工厂方法模式给我们的启迪:
      如果不使用工厂模式来实现我们的例子,也许代码会减少很多--只需要实现已有的车,不使用多态。但是在可维护性上,可扩展性上是非常差的(你可以想象一下,添加一辆车后要牵动的类)。因此为了提高扩展性和维护性,多写些代码是值得的。

六、抽象工厂模式
      先来认识下什么是产品族:位于不同产品等级结构中,功能相关联的产品组成的家族。如果光看这句话就能清楚的理解这个概念,我不得不佩服你啊。还是让我们用一个例子来形象地说明一下吧。

      BmwCar和BenzCar就是两个产品树(产品层次结构);而BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzSportsCar也是一个产品族。
      回到抽象产品模式的话题上,可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品一起使用。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
 1)抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
 2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
 3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
 4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

clip_image008

      看过了前两个模式,对这个模式各个角色之间的协调情况应该心里有个数了,我就不举具体的例子了。只是一定要注意满足使用抽象工厂模式的条件哦,不然即使存在了多个产品树,也存在产品族,但是不能使用的。