工厂模式

设计模式之简单讨论

前言:

设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。

设计模式总共23种,这些模式可以分为三大类:创建型模式、结构型模式、行为型模式。

1:工厂模式

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

a:简单工厂模式(创建型)

简单工厂:它属于类创建型模式。在简单工厂模式中,可以根据自变量的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

简单工厂模式角色

1)工厂类(Creator)角色:担任这个角色的是工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体Java 类实现。 

2)抽象产品(Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口抽象产品角色可以用一个Java 接口或者Java 抽象类实现。 

3)具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色由一个具体Java 类实现。

 

 

简单工厂模式的优点

1)工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。

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

简单工厂模式的适用环境 

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

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

代码说明

//抽象产品角色

我喜欢吃面条,抽象一个面条基类,(接口也可以),这是产品的抽象类。

public abstract class INoodles {

    //描述每种面条啥样的

    public abstract void desc();

}

//具体产品角色

先来一份兰州拉面(具体的产品类):

public class LzNoodles extends INoodles {

    @Override

    public void desc() {

        System.out.println("上海的好贵 家里才8块钱一碗");

    }

}

 

//具体产品角色

程序员加班必备也要吃泡面(具体的产品类):

public class PaoNoodles extends INoodles {

    @Override

    public void desc() {

        System.out.println("泡面好吃 可不要贪杯");

    }

}

//工厂类角色

准备工作OK,我们来到一家“简单面馆”(简单工厂类),菜单如下:

public class SimpleNoodlesFactory {

    public static final int TYPE_LZ = 1; //兰州拉面

    public static final int TYPE_PM = 2; //泡面

 

 

    public static INoodles createNoodles(int type) {

        switch (type) {

            case TYPE_LZ:

                return new LzNoodles();

            case TYPE_PM:

                return new PaoNoodles();

            default:

               return new PaoNoodles();

        }

    }

}

//使用

工厂提供种面条(产品),你说你要啥,他就给你啥。这里我点了一份泡面:

 INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_PM);

 noodles.desc();

 

 

思考:如何拓展一个新产品

      1:新添加一个接口的实现类 即新产品的定义

      2:工厂方法添加生产这种产品的业务逻辑

 

这显然不符合“开闭原则(对扩展开放;对修改封闭)

 

 

b工厂方法模式

工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。 来看下它的组成:

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

 

//抽象产品角色

public interface Moveable {

  void run();

}

//具体产品角色

public class Plane implements Moveable {

  @Override

  public void run() {

    System.out.println("plane....");

  }

}

public class Broom implements Moveable {

  @Override

  public void run() {

    System.out.println("broom.....");

  }

}

//抽象工厂

public abstract class VehicleFactory {

  abstract Moveable create();

}

//具体工厂

public class PlaneFactory extends VehicleFactory{

  public Moveable create() {

    return new Plane();

  }

}

public class BroomFactory extends VehicleFactory{

  public Moveable create() {

    return new Broom();

  }

}

//测试类

public class Test {

  public static void main(String[] args) {

    VehicleFactory factory = new BroomFactory();

    Moveable m = factory.create();

    m.run();

  }

}

 

思考:如何拓展一个新产品

      1:新添加一个接口的实现类 即具体产品

      2:添加一个具体的生产工厂

已经符合了开闭原则

工厂方法模式的缺点

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

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

 

c抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而构成一个或多个产品族(Product Family) 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。

产品族:是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法模式提供的一系列产品称为一个等级结构。使用生产汽车的例子来说明他们之间的区别。两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。

 

适用场景

       当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。

系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。

系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

//抽象产品

interface IProduct1 {  

    public void show();  

}  

//抽象产品

interface IProduct2 {  

    public void show();  

}  

  //具体产品

class Product1 implements IProduct1 {  

    public void show() {  

        System.out.println("这是1型产品");  

    }  

}  

//具体产品

class Product2 implements IProduct2 {  

    public void show() {  

        System.out.println("这是2型产品");  

    }  

}  

  //抽象工厂

interface IFactory {  

    public IProduct1 createProduct1();  

    public IProduct2 createProduct2();  

}  

//具体工厂

class Factory implements IFactory{  

    public IProduct1 createProduct1() {  

        return new Product1();  

    }  

    public IProduct2 createProduct2() {  

        return new Product2();  

    }  

}  

  

//测试

public class Client {  

    public static void main(String[] args){  

        IFactory factory = new Factory();  

        factory.createProduct1().show();  

        factory.createProduct2().show();  

    }  

}

 

思考

a 若要给当前产品族新增加一个产品

b 若要新增加一个产品族

当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。

当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。

 

 

抽象工厂模式有哪些优点

1、最大的好处便是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同产品配置。

2、它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。

 

posted @ 2020-09-07 18:57  春意了无痕  阅读(87)  评论(0)    收藏  举报