设计模式——工厂模式

来源:互联网 发布:淘宝店铺免费一键复制 编辑:程序博客网 时间:2024/05/20 05:30

无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦

使用工厂方法模式,看上去会感觉到这不是更麻烦了吗,直接在外界创建具体的抽象子类不行吗?还用这么麻烦的创建工厂子类,然后再用工厂子类去创建抽象子类。

1 工厂方法封装了对象创建的细节,将对象创建代码和其他部分脱离,减少相干性.
2 有利于同类对象创建的统一管理和控制
3 你所关心的仅仅是工厂方法返回的接口方法,不必关心实现细节

为什么不直接用new呢?
我是这样理解的:(1)构造对象同时还需要对对象进行初始化,如果都放在构造函数里由new操作符调用,可能导致构造函数很长。这种将很多工作都放在构造函数中的做法相当危险,因此需要一个专门生产对象,并适当初始化的工厂。(2)项目中可能会有很多继承于相同class的子类,每一个子类实例化都用new将是一件费力的事,不如将这些重复的工作交给类工厂。(3)有时候,我们不需要多个对象事例(只需要一个),通常用new操作无法完成。

我将从两方面回答这个问题:
  1. 假设现在项目比较大,在外界很多地方都直接使用了抽象子类直接进行运算,这种方式在写代码的时候确实很快也很爽。但是,假设有一天,产品经理过来说要改需求,我现在不要加减乘除这四种运算了,我要换成更高级的其他运算。。。如果这样改起来改动就大了,需要把所有直接使用抽象子类实例化的地方都做修改。

  2. 这只是一种设计模式的思路,在程序的开发中没有一种设计模式是万能的,在适合的地方用适合的设计模式,或根据业务需求自己制定一套模式,这才是最好的。只有最适合业务的模式,才是最好的模式

    工厂就是你要什么去到工厂里拿就好了,工厂负责生产,你除了使用什么都不用管,小程序你看不出优势来,打个比方说如果12亿人人,一人一个电视,那么如果每个人都去工厂里制造是多么麻烦的事,你只要告诉他你要什么类型的,工厂会生产出来给你,这个就是通俗意义上的工厂模式了。
    至于说使用这个的好处,可以方便的更改应用程序,方便扩展。比如说你修改了一个类,或者在这个类的基础上生成了一个子类那么你现在要把以前使用父类的地方都给改为子类,如果小程序可能有几十个地方要改,如果大一点可能就几百几千个地方要改了。如果使用工厂模式,你只要改一个地方就可以了。

    简单的工厂模式

    //抽象产品角色    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();         }     }

    简单工厂模式的优点如下: 

    (1)工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。 (2)客户端无需知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。 

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

    简单工厂模式的缺点如下: 

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

    (2)使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。 

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

    (3)简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

    2.4简单工厂模式的适用环境 

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

    (2)客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。



    工厂方法模式

    //抽象产品  PenCore.java public abstract class PenCore{     String color;     public abstract void writeWord(String s); } //具体产品 RedPenCore.java public class RedPenCore extends PenCore {      RedPenCore() {           color = "红色";      }      public void writeWord(String s) {           System.out.println("写出" + color + "的字" + s);      } }BluePenCore.java public class BluePenCore extends PenCore {      BluePenCore() {           color = "蓝色";     }    public void writeWord(String s) {           System.out.println("写出" + color + "的字" + s);      } } BlackPenCore.java public class BlackPenCore extends PenCore {      BlackPenCore() {           color = "黑色";      }    public void writeWord(String s) {           System.out.println("写出" + color + "的字" + s);      } } //构造者 BallPen.java public abstract class BallPen {      BallPen(){           System.out.println("生产一只装有"+getPenCore().color+"笔芯的圆珠笔");      }    public abstract PenCore getPenCore(); } //具体构造者 RedBallPen.java public class RedBallPen extends BallPen {     public PenCore getPenCore() {        return new RedPenCore();      } } BlueBallPen.java public class BlueBallPen extends BallPen {      public PenCore getPenCore() {          return new BluePenCore();      } } BlackBallPen.java public class BlackBallPen extends BallPen {     public PenCore getPenCore() {           return new BlackPenCore();      } }


    工厂方法模式的优点如下: 

    (1)在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类的类名。 

    (2)基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,正是因为所有的具体工厂类都具有同一抽象父类。

    (3)使用工厂方法模式的另一个优点是在系统中加入新产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。 

    工厂方法模式的缺点如下:

    (1)在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

    (2)由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

    3.4工厂方法模式的适用环境 

    在以下情况下可以使用工厂方法模式: 

    (1)一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。 

    (2)一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

    (3)将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。



    抽象工厂模式

    //抽象产品 UpperClothes.javapublic abstract class UpperClothes {      public abstract int getChestSize();      public abstract int getHeight();      public abstract String getName(); } Trousers.java public abstract class Trousers {      public abstract int getWaistSize();      public abstract int getHeight();      public abstract String getName(); }//具体产品 WesternUpperClothes.java public class WesternUpperClothes extends UpperClothes {      private int chestSize;      private int height;      private String name;     WesternUpperClothes(String name,int chestSize,int height){           this.name=name;           this.chestSize=chestSize;           this.height=height;      }    public int getChestSize() {           return chestSize;     }     public int getHeight() {           return height;      }      public String getName() {           return name;      } }CowboyUpperClothes.java public class CowboyUpperClothes extends UpperClothes {      private int chestSize;      private int height;      private String name;     CowboyUpperClothes(String name,int chestSize,int height){           this.name=name;           this.chestSize=chestSize;           this.height=height;     }    public int getChestSize() {          return chestSize;     }     public int getHeight() {           return height;     }    public String getName () {           return name;      } }WesternTrousers.java public class WesternTrousers extends Trousers {      private int waistSize;      private int height;      private String name;     WesternTrousers(String name,int waistSize,int height){           this.name=name;           this.waistSize=waistSize;           this.height=height;     }     public int getHeight() {           return height;      }     public String getName() {        return name;     }     public int getWaistSize() {           return waistSize;     } } CowboyTrousers.javapublic class CowboyTrousers extends Trousers {      private int waistSize;      private int height;      private String name;     CowboyTrousers(String name,int waistSize,int height){           this.name=name;           this.waistSize=waistSize;           this.height=height;     }     public int getHeight() {           return height;      }     public String getName() {           return name;      }    public int getWaistSize() {           return waistSize;     } } //抽象工厂 ClothesFactory.java public abstract class ClothesFactory {      public abstract UpperClothes createUpperClothes(int chestSize,int height);      public abstract Trousers createTrousers(int waistSize,int height); }//具体工厂 BeijingClothesFactory.java public class BeijingClothesFactory extends ClothesFactory {      public Trousers createTrousers(int waistSize, int height) {           return new WesternTrousers("北京牌裤子",waistSize,height);      }     public UpperClothes createUpperClothes(int chestSize, int height) {           return new WesternUpperClothes("北京牌上衣",chestSize,height);      } }ShanghaiClothesFactory.java public class ShanghaiClothesFactory extends ClothesFactory {     public Trousers createTrousers(int waistSize, int height) {           return new WesternTrousers("上海牌裤子",waistSize,height);     }     public UpperClothes createUpperClothes(int chestSize, int height) {           return new WesternUpperClothes("上海牌上衣",chestSize,height);      } }


    4.3抽象工厂模式的优缺点 

    优点: 

    (1) 隔离了具体类的生成,使得用户不需要知道什么被创建了。 

    (2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终

    只使用同一个产品族中的对象。 缺点: 

    (1)添加新的产品对像时,难以扩展抽象工厂以便生产新种类的产品。

    4.4抽象工厂模式的适用环境 

    (1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。这对于所有形态的工厂模式都是重要的; 

    (2)一个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品; (3)同属于同一个产品族的产品是在一起使用的,这一约束必须要在系统的设计中体现出来; 

    (4)系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。



0 0
原创粉丝点击