浅学设计模式之简单工厂模式、工厂模式、抽象工厂模式

来源:互联网 发布:全球离婚率数据 编辑:程序博客网 时间:2024/05/17 13:43


一、简单工厂

        从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

      其包括三个角色:


  1.  工厂(Creator)角色 :简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
  2.  抽象产品(Product)角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  3.  具体产品(Concrete Product)角色:是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

其UML图如下所示:



看一下写的小例子:假如一家航空公司需要购买飞机:

先定义飞机接口:

[java] view plaincopy
  1. public interface IPlane {  
  2.     void name();  
  3. }  

在得到Product:

波音:

[java] view plaincopy
  1. public class Boeing777 implements IPlane{  
  2.     private String name = "Boeing777";  
  3.     @Override  
  4.     public void name() {  
  5.         // TODO Auto-generated method stub  
  6.         System.out.println("My name is:" + name);  
  7.     }  
  8.   
  9. }  

空客:

[java] view plaincopy
  1. public class Boeing737 implements IPlane {  
  2.     private String name = "Boeing737";  
  3.     @Override  
  4.     public void name() {  
  5.         // TODO Auto-generated method stub  
  6.         System.out.println("My name is :" + name);  
  7.     }  
  8.   
  9. }  

再看飞机工厂:

Create:

[java] view plaincopy
  1. public class PlaneFactory {  
  2.     public static IPlant getPlane(String name) throws Exception {  
  3.         if (name.equalsIgnoreCase("boeing777")){  
  4.             return new Boeing777();  
  5.         } else if (name.equalsIgnoreCase("boeing737")){  
  6.             return new Boeing737();  
  7.         }else  
  8.         {  
  9.             throw new Exception("The type $type don't exists" );  
  10.         }         
  11.     }  
  12. }  

当我们在客户端想要得到飞机的时候:

[java] view plaincopy
  1. public class PlaneTest {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      * @throws Exception  
  6.      */  
  7.     public static void main(String[] args) throws Exception {  
  8.         // TODO Auto-generated method stub  
  9.         //获取波音飞机  
  10.         IPlane boeing777 = PlaneFactory.getPlane("boeing777");  
  11.         //获得名字  
  12.         boeing777.name();  
  13.         //获取空客飞机  
  14.         IPlane boeing737= PlaneFactory.getPlane("airbus");  
  15.         //获得名字  
  16.         boeing737.name();  
  17.     }  
  18.   
  19. }  

运行结果:

My name is:Boeing777
My name is :Boeing737


优点:

  工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点:
  由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
  当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
  这些缺点在工厂方法模式中得到了一定的克服。
使用场景
  工厂类负责创建的对象比较少;
  客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;

  由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

 说明:

        以上文字概念部分,均来自百度百科。自己没有那么好的归纳能力。


二、工厂模式




5月23号修改工厂模式代码,把工厂类修改成抽象类:

[java] view plaincopy
  1. public abstract class PlaneFactory {  
  2.     public void letPlaneFly(String name){  
  3.         IPlane iPlane = getPlane(name);  
  4.         iPlane.fly();  
  5.     }  
  6.     abstract IPlane getPlane(String name) ;  
  7. }  

不但能获取飞机,而且能让它飞!

具体工厂类,有boeing工厂和airbus工厂。

[java] view plaincopy
  1. public class AirbusFactory extends PlaneFactory {  
  2.   
  3.     @Override  
  4.     IPlane getPlane(String name) {  
  5.         // TODO Auto-generated method stub  
  6.         if (name.equalsIgnoreCase("airbus320")){  
  7.             return new Airbus320();  
  8.         } else if (name.equalsIgnoreCase("airbus380")){  
  9.             return new Airbus380();  
  10.         }else {  
  11.             return null;  
  12.         }  
  13.     }  
  14.   
  15. }  

[java] view plaincopy
  1. public class BoeingPlaneFactory extends PlaneFactory{  
  2.   
  3.     @Override  
  4.     IPlane getPlane(String name) {  
  5.         // TODO Auto-generated method stub  
  6.         if (name.equalsIgnoreCase("boeing777")){  
  7.             return new Boeing777();  
  8.         } else if (name.equalsIgnoreCase("boeing737")){  
  9.             return new Boeing737();  
  10.         }else {  
  11.             return null;  
  12.         }         
  13.     }  
  14.   
  15.       
  16. }  

产品抽象类:plane

[java] view plaincopy
  1. public abstract class IPlane {  
  2.     abstract void name();  
  3.     public void fly() {  
  4.         name();  
  5.         System.out.println("i fly in the sky");  
  6.     }  
  7. }  

分别继承,获得的四个飞机类:

[java] view plaincopy
  1. public class Boeing777 extends IPlane {  
  2.   
  3.     @Override  
  4.     public void name() {  
  5.         // TODO Auto-generated method stub  
  6.         System.out.println("i am boeing 777");  
  7.     }  
  8.   
  9. }  

[java] view plaincopy
  1. public class Boeing737 extends IPlane {  
  2.   
  3.     @Override  
  4.     public void name() {  
  5.         // TODO Auto-generated method stub  
  6.         System.out.println("i am boeing 737");  
  7.     }  
  8.   
  9. }  


[java] view plaincopy
  1. public class Airbus320 extends IPlane {  
  2.   
  3.     @Override  
  4.     public void name() {  
  5.         // TODO Auto-generated method stub  
  6.         System.out.println("i am airbus320");  
  7.     }  
  8.   
  9. }  

[java] view plaincopy
  1. public class Airbus380 extends IPlane {  
  2.   
  3.     @Override  
  4.     public void name() {  
  5.         // TODO Auto-generated method stub  
  6.         System.out.println("i am Airbus380");  
  7.     }  
  8.   
  9. }  

测试类:

[java] view plaincopy
  1. public static void main(String[] args) throws Exception {  
  2.         PlaneFactory airBus = new AirbusFactory();  
  3.         //看空客飞机飞  
  4.         airBus.letPlaneFly("airbus320");  
  5.         airBus.letPlaneFly("airbus380");  
  6.         PlaneFactory boeing = new BoeingPlaneFactory();  
  7.         boeing.letPlaneFly("boeing777");  
  8.         boeing.letPlaneFly("boeing737");  
  9.           
  10.     }  

测试结果:

i am airbus320
i fly in the sky
i am Airbus380
i fly in the sky
i am boeing 777
i fly in the sky
i am boeing 737
i fly in the sky


三、抽象工厂模式

        当我们发现,我们不仅需要民航飞机,我们还需要战斗机,该如何办呢?大家都知道,波音不仅生产民用飞机,还有著名的B-52,而空客也有它的军用运输机A400M。

我们生产飞机时,就需要两个接口了,军用飞机一个接口,民用飞机一个接口。看下图:


军用飞机是一个产品等级,民用飞机又是一个产品等级,而波音和空客生产两个不同的产品族。


先看看民用飞机接口:

[java] view plaincopy
  1. public interface ICivilaircraft {  
  2.     String getName();  
  3.     //运输旅客  
  4.     void passengers();  
  5. }  

民用飞机:

[java] view plaincopy
  1. public class Boeing777 implements ICivilaircraft{  
  2.     private String name ="Boeing 777";  
  3.     private String personNumber ="350";  
  4.   
  5.     @Override  
  6.     public String getName() {  
  7.         return name;  
  8.         // TODO Auto-generated method stub  
  9.           
  10.     }  
  11.   
  12.     @Override  
  13.     public void passengers() {  
  14.         // TODO Auto-generated method stub  
  15.         System.out.println(getName()+"can passengers "+personNumber+" person");  
  16.     }  
  17. }  

空客的空客340

[java] view plaincopy
  1. public class Airbus340 implements ICivilaircraft{  
  2.     private String name ="Airbus340";  
  3.     private String personNumber ="380";  
  4.   
  5.     @Override  
  6.     public String getName() {  
  7.         return name;  
  8.         // TODO Auto-generated method stub  
  9.           
  10.     }  
  11.   
  12.     @Override  
  13.     public void passengers() {  
  14.         // TODO Auto-generated method stub  
  15.         System.out.println(getName()+"can passengers "+personNumber+" person");  
  16.     }  
  17. }  


军用飞机接口:

[java] view plaincopy
  1. public interface IWarplane  {  
  2.     String getName();  
  3.     //运输武器  
  4.     void Transportarms();  
  5. }  

军用飞机:

[java] view plaincopy
  1. public class A400M implements IWarplane {  
  2.     private String name ="A400M";  
  3.     private String armweight="30吨";  
  4.     @Override  
  5.     public String getName() {  
  6.         // TODO Auto-generated method stub  
  7.         return name;  
  8.     }  
  9.   
  10.     @Override  
  11.     public void Transportarms() {  
  12.         // TODO Auto-generated method stub  
  13.         System.out.println(getName()+"can transport "+ armweight+" arms");  
  14.     }  
  15.   
  16. }  

B52:

[java] view plaincopy
  1. public class B52 implements IWarplane {  
  2.     private String name ="B52";  
  3.     private String armweight="27吨";  
  4.     @Override  
  5.     public String getName() {  
  6.         // TODO Auto-generated method stub  
  7.         return name;  
  8.     }  
  9.   
  10.     @Override  
  11.     public void Transportarms() {  
  12.         // TODO Auto-generated method stub  
  13.         System.out.println(getName()+"can transport "+ armweight+" arms");  
  14.     }  
  15.   
  16. }  

在看看飞机工厂,波音公司和空客公司,先看他们的父类:

[java] view plaincopy
  1. public abstract class AbstractFactory {  
  2.     abstract ICivilaircraft getCivilair();  
  3.     abstract IWarplane getWarplane();  
  4. }  

波音:

[java] view plaincopy
  1. public class BoeingFactory extends AbstractFactory{  
  2.   
  3.     @Override  
  4.     ICivilaircraft getCivilair() {  
  5.         // TODO Auto-generated method stub  
  6.         return new Boeing777();  
  7.     }  
  8.   
  9.     @Override  
  10.     IWarplane getWarplane() {  
  11.         // TODO Auto-generated method stub  
  12.         return new B52();  
  13.     }  
  14.       
  15.   
  16. }  

空客:

[java] view plaincopy
  1. public class AirBus extends AbstractFactory {  
  2.   
  3.     @Override  
  4.     ICivilaircraft getCivilair() {  
  5.         // TODO Auto-generated method stub  
  6.         return new Airbus340();  
  7.     }  
  8.   
  9.     @Override  
  10.     IWarplane getWarplane() {  
  11.         // TODO Auto-generated method stub  
  12.         return new A400M();  
  13.     }  
  14.   
  15. }  

测试类:

[java] view plaincopy
  1. public static void main(String[] args) {  
  2.         // TODO Auto-generated method stub  
  3.         AbstractFactory boeing = new BoeingFactory();  
  4.         AbstractFactory airbus = new AirBus();  
  5.         //查看波音的民用飞机  
  6.         boeing.getCivilair().passengers();  
  7.         //查看波音的军用飞机  
  8.         boeing.getWarplane().Transportarms();  
  9.         //查看空客的民用飞机  
  10.         airbus.getCivilair().passengers();  
  11.         //查看空客的军用飞机  
  12.         airbus.getWarplane().Transportarms();  
  13.     }  

测试结果:

Boeing 777  can passengers 350 person
B52  can transport 27吨 arms
Airbus340  can passengers 380 person
A400M  can transport 30吨 arms


区别和联系:

抽象工厂和工厂模式有什么区别呢?他们俩又在具体什么情况下使用呢?请看下面从网上找到的不错的回答:


      其实这两者的区别,GOF的书上说得很清楚。工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象)。而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。


工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。   一个抽象工厂类,可以派生出多个具体工厂类。   每个具体工厂类只能创建一个具体产品类的实例。抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   一个抽象工厂类,可以派生出多个具体工厂类。   每个具体工厂类可以创建多个具体产品类的实例。       区别:工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。


工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。工厂方法:说白了就是一个方法,这个方法是创建具体的产品的,它要求所有的工厂都具有同一个签名的方法,必要时重写该方法;抽象工厂:不能直接创建产品,只能创建工厂,即抽象工厂创建的产品是工厂。虽然它也定义了创建产品的方法,但需要创建出来的具体的工厂实现,即:抽象工厂创建出的工厂创建产品。工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象);而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。


可以这么去理解,“抽象工厂模式”这个称呼中的“抽象”是一个动词,即对工厂方法模式进行了抽象,就变成了抽象工厂模式,这么理解后,就不难看出它们的区别: 工厂方法模式:每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一个具体产品的实例创建; 抽象工厂模式:每个抽象产品派生多个具体产品类,每个抽象工厂派生多个具体工厂类,每个具体工厂负责多个(一系列)具体产品的实例创建。


原文地址:http://blog.csdn.net/lilu_leo/article/details/7592678