zoukankan      html  css  js  c++  java
  • 工厂方法模式

    工厂模式 - 20141028

    ——实例化不公开。

    ——识别变化的部分,封装变化的部分:封装创建对象的代码。

             封装对象的创建。【封装改变】让子类决定创建什么对象。

             工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。

             工厂方法让类把实例化推迟到子类。

    1.工厂方法模式。      2.抽象工厂模式。

    简单工厂模式:

    public class SimplePizzaFactory    【工厂不是抽象的】

    {

     public Pizza createPizza(String type)

     {

      Pizza pizza = null;

      ...

     }

     public class PizzaStore

     {

      SimplePizzaFactory factory;

      public PizzaStore(SimplePizzaFactory factory)

      {

       this.factory = factory;

      }

      public Pizza orderPizza(String type)

      {

       Pizza pizza;

       pizza = factory.createPizza(type);      【此处不用new创建对象】【创建对象:Pizza】

      }

     }

    }

    ——abstract Produce factoryMethod (String type)

    工厂方法:将客户点披萨orderPizza()和实际创建具体产品的代码分隔开。

    ——调用使用:

    PizzaStore nyPizzaStore = new NYPizzaStore();//建立实例

    nyPizzaStore.orderPizza("cheese");

    //相当于隐含调用 Pizza pizza = createPizza("cheese");

    ——依赖倒置原则:

             要依赖抽象,不要依赖具体类。

             不能让高层组件依赖底层组件。而且不管高层或底层组件,都应该依赖于抽象。

             依赖抽象层,而不依赖具体类。

    1.变量不持有具体类的引用,避开new。

    2.不让类派生自具体类,请派生自一个抽象(接口或抽象类)

    3.不覆盖基类中已实现的方法。

    抽象工厂模式:【多个工厂】

             提供一个接口,用于创建相关或依赖对象的家族。而不许明确指定具体类。

             (通过对象的组合)

    public interface PizzaIngredientFactory    【工厂是抽象的】

    {

     public Dough createDough();

     public Sauce createSauce();

     ...

    }

    +++++++++++++++++++++++++++

    public class NYPizzaIngredientFactory implements PizzaIngredientFactory

    {

     public Dough createDough(){      【工厂内部可以创建多种类似的产品!!!】

      return new ThinCrustDough();

     }

     public Sauce createSauce(){

      return new MarinareSource();

     }

    }

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    public abstract class Pizza{

     String name;

     Dough dough;

     Sauce sauce;

     abstract void prepare();

     void cut(){...}

    }

    +++++++++++++++++++++++++++

    public class CheesePizza extends Pizza{       【CheessPizza(Pizza) -> PizzaIngredientFactory(NYPizza…)】

     PizzaIngredientFactory ingredientFactory;     //对象组合

     public CheesePizza(PizzaIngredientFactory ing){

      this.ingredientFactory = ing;

     }

     void prepare(){

      //工厂创建对象

      dough = ingredientFactory.createDough();

     }

    }

    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    public class NYPizzaStore extends PizzaStore{

     protected Pizza createPizza(String item){

      Pizza pizza = null;    【组合Pizza对象】

      PizzaIngredientFactory ing = new NYPizzaIngredientFactory();【组合Factory对象】

    【无法确切知道是哪个工厂,因为工厂可以切换。】

      if(item.equals("cheese")){

       pizza = new CheesePizza(ing);      //把工厂对象作为参数传入构造函数

                        【比如也可以传new CheesePizza(new GuangZhouPizzaIngredientFactory())】

       pizza.setName("NY Cheese");     【Pizza对象内部组合了工厂对象,可以Pizza调用“具体工厂”的设置对象方法】

      }                                【Pizza对象中有工厂】

      return pizza;

     }

    }

    《Java工厂模式》

             http://blog.csdn.net/zxl0016/article/details/7922384

             有 一个****户,他家有三辆汽车——Benz奔驰、Bmw宝马、Audi奥迪,还雇了司机为他开车。不过,****户坐车时总是怪怪的:上Benz车后跟 司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上Audi说“开奥迪车!”。你一定说:这人有病!直接说开车不就行了?!

             工厂模式主要是为创建对象提供过渡接口,以便“将创建对象的具体过程”屏蔽隔离起来,达到提高灵活性的目的。

    工厂模式在《Java与模式》中分为三类:

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

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

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

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

             GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(FactoryMethod)与抽象工厂模式(Abstract Factory)将简单工厂模式(SimpleFactory)看为工厂方法模式的一种特例,两者归为一类。

             两者皆可,在本文使用《Java与模式》的分类方法。下面来看看这些工厂模式是怎么来“治病”的。

    简单工厂模式 - 又称“静态工厂方法”模式。目的:定义一个用于创建对象的接口。

    //抽象产品角色

    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】

                                 //下命令:开车

                                     car.drive();    【调用具体汽车的开车方法】

                           。。。 

    客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品。

    工厂方法模式

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

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

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

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

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

          工厂方法模式使用【继承自抽象工厂角色的多个子类】来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构 变得灵活起来——当有新的产品(即****户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改 任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的!

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

    //抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。【一个抽象产品角色】

    public interface Driver{    【//抽象工厂角色】

           public Car driverCar();

    }

    public class BenzDriver implements Driver{

             public Car driverCar(){

                return new Benz();【返回Car对象】【仅仅是单个对象:如果工厂可以建立一组对象就是抽象工厂】

             }}

    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();       【使用方式:工厂对象Driver内返回Car对象】【Car是由工厂产生的!】

                         }

                 ……

    }

             可 以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况, 可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。

    五、小结

             工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以考虑使用工厂方法模式:

         1)当客户程序不需要知道要使用对象的创建过程。

         2)客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。

             简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;

             而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。

           面对这种情况,【Java的反射机制与配置文件】的巧妙结合突破了限制——这在Spring中完美的体现了出来。 

    抽象工厂模式【工厂本身是抽象的】

             先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。还是让我们用一个例子来形象地说明一下吧。回到抽象工厂模式的话题上。

             可以说,抽象工厂模式和工厂方法模式的区别就在于【需要创建对象的复杂程度上】。而且抽象工厂模式是三个里面最为抽象、最具一般性的。

             抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。

    而且使用抽象工厂模式还要满足一下条件:

         1)系统中有多个产品族,而系统一次只可能消费其中一族产品。

         2)同属于同一个产品族的产品以其使用。

    来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):

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

         2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。

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

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

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

        可以这么去理解,“抽象工厂模式”这个称呼中的“抽象”是一个动词,即对工厂方法模式进行了抽象,就变成了抽象工厂模式,这么理解后,就不难看出它们的区别:
        工厂方法模式:每个抽象产品派生多个具体产品类,每个抽象工厂类派生多个具体工厂类,每个具体工厂类负责一个具体产品的实例创建;
        抽象工厂模式:每个抽象产品派生多个具体产品类,每个抽象工厂派生多个具体工厂类,每个具体工厂负责多个(一系列)具体产品的实例创建。
        你在下面所说的一句话“抽象工厂的具体工厂经常实现工厂方法来创建他的产品”,这句话里面的“工厂方法”仅仅是对一类方法的称呼,此处的“工厂方法”与“工厂方法模式”无关,即便在简单工厂模式中,也会有工厂方法这一说。

    《抽象工厂模式-与-工厂方法模式区别》

           工厂模式:    定义一个用于创建对象的接口,让子类决定实例化哪一个类。

           抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

           工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。

    http://blog.csdn.net/wyxhd2008/article/details/5597975

    工厂方法模式

    抽象工厂模式

    针对的是一个产品等级结构

    针对的是面向多个产品等级结构

    一个抽象产品类

    多个抽象产品类

    可以派生出多个具体产品类

    每个抽象产品类可以派生出多个具体产品类

    一个抽象工厂类,可以派生出多个具体工厂类

    一个抽象工厂类,可以派生出多个具体工厂类

    每个具体工厂类只能创建一个具体产品类的实例

    每个具体工厂类可以创建多个具体产品类的实例

    【抽象工厂就是你生产产品的时候,不知道是哪些工厂】

    【调用哪一个具体工厂要根据菜的种类决定,转基因根菜就需要使用转基因工厂中的种根菜方法。该工厂也可以种jin菜。】

             上面的UML图很明显的就看出来了,抽象工厂可以创建多个产品类对象,如在种菜工厂中,有种根菜,种茎菜。工厂模式与抽象工厂模式以及简单工厂模式只有在具体应用的时候,分析具体的产品层级,然后选择相应的设计模式。

    而在每一个层次,种菜工人所关心的对象也不一样,在简单工厂模式下,工人要想到种植萝卜还是白菜,在工厂模式下,工人想到是种植根菜还是茎菜,而在抽象工厂模式下,则关心种植基因菜还是非基因菜

    工厂创建一种产品,抽象工厂创建的是一组产品,是一个产品系列(电脑+服务器,根菜+茎菜)。

    这里要注意的是“系列”的意思,也就是说,抽象工厂创建出的一组产品是成套的。

    当你发现,有一个接口可以有多种实现的时候,可以考虑使用工厂方法来创建实例。

    当你发现,有一组接口可以有多种实现方案的时候,可以考虑使用抽象工厂创建实例组。

    (一组接口:做电脑+做服务器,种根菜+种茎菜。)

    单看IBMFactory或者DellFactory, 那就是 工厂方法模式

    看整张图,就是 抽象工厂模式。。(就是工厂本身也是抽象的:可以有生产IBM的工厂,或者生产Dell的工厂。)

    总结:

           关键点在于,抽象工厂的每个工厂中,可以创建多个种类的产品。第二级具体产品:比如PC(根菜)/Server(茎菜)。

           该抽象工厂表明了一个属性,第一级属性。

           比如是IBM家的(转基因工厂)还是Dell家(非转基因工厂)。

           IBMFactory(IBM工厂),DellFactory(Dell工厂)。这两个工厂,每个工厂又可以生产第二级几个具体产品。

           转基因工厂可以生产“转基因根菜”,或者“转基因茎菜”。

           IBM工厂  可以生产 “IBM电脑” ,  或者  “IBM服务器”。

  • 相关阅读:
    java线程(1)-线程同步
    Scala:(3)数组
    Codeforces 899F Letters Removing
    拼图游戏的可解性
    Hash
    哈夫曼编码
    莫比乌斯
    FFT
    Ropes
    区间合并
  • 原文地址:https://www.cnblogs.com/lsx1993/p/4631782.html
Copyright © 2011-2022 走看看