原创

详解设计模式—抽象工厂模式(Abstract FActory Pattern)

定义

provide an interface for creating families of related or dependent object without specifying their concrete class.(为创建一组相关或者互相依赖的对象提供一个接口,而且无需指定他们的具体实现类。)

创建型模式

角色

AbstractFactory:抽象工厂
  • 声明一个创建抽象产品的对象的操作接口
    ConcreteFactory:具体工厂
  • 实现创建具体产品对象的操作
    AbstractProduct:抽象产品
  • 为一类产品对象生命的一个接口
    ConcreteProduct:具体产品
  • 定义一个将被相应的具体工厂创建的产品对象

协作

  • 通常在运行时刻创建一个 ConcreteFactory 累的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应该使用不同的具体工厂。
  • AbstracFactory 将产品对象的创建延迟到他的ConcreteFactory子类。

    类图

20190713221926580.png

使用场景

抽象工厂的使用场景如下(设计模式书中给出):

  • 一个系统要独立于他的产品创建、组合和表示时;
  • 一个系统要由多个产品系列中的一个来配置时;
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时;
  • 当你提供一个类库,而只想显示接口而不是实现时;

通俗一点讲:一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。什么意思呢?例如一个文本编辑器和一个图片处理器,都是软件实体,但是Linux下的文本编辑器和Windows下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也有类似情况。也就是具有了共同的约束条件:操作系统类型。于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。

优点

  • 封装性,抽象工厂模式分离了具体的类,帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,他将客户与类的实现分离,产品的类名也被具体工厂的实现分离,不会出现在客户端代码中。也就是说每个产品的实现类是不需要客户关心的,他们只需要关心接口和抽象即可,只要知道了工厂类,就可以创建出客户端需要的对象就可以了。
  • 有利于产品的一致性,当一个系列中的产品被设计成一起工作时,一个应用只能使用同一个系列中的对象。

缺点

  • 拓展性较差,难以拓展抽象工厂以生产新种类的产品。这是因为AbstractFactory 接口确定了可以被创建的产品集合。如果要支持新的产品,那么就需要拓展改工厂接口,这一过程将会影响到其他已经实现的子类,这不符合设计模式中的开闭原则,但这也是只针对对种类的拓展。

注意事项

  • “开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:
    1. 增加产品族:对于增加新的产品族,工厂方法模式很好的支持了“开闭原则”,对于新增加的产品族,只需要对应增加一个新的具体工厂即可,对已有代码无须做任何修改。
    2. 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,不能很好地支持“开闭原则”。

抽象工厂模式的这种性质称为“开闭原则”的倾斜性,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,但不能为新的产品等级结构的增加提供这样的方便。

举个:chestnut:

以人类为例子,产品等级中只有男、女两个性别,现实世界还有一种性别:双性人,既是男人也是女人,那我们要扩展这个产品等级也是非常容易的,增加三个产品类,分别对应不同的肤色,然后再创建一个工厂类,专门负责不同肤色人的双性人的创建任务,完全通过扩展来实现需求的变更,从这一点上看,抽象工厂模式是符合开闭原则的。

具体实现

抽象产品A类

public abstract class AbstractProductA {   
     //每个产品共有的方法
     public void shareMethod(){
         System.out.println(" A类共有方法!");
     }
     //每个产品相同方法,不同实现
     public abstract void doSomething();
}

产品A1的实现类

public class ProductA1 extends AbstractProductA {
     public void doSomething() {
             System.out.println("产品A1的实现方法");
     }
}

产品A2的实现类

public class ProductA2 extends AbstractProductA {
     public void doSomething() {
             System.out.println("产品A2的实现方法");
     }
}

抽象产品B类

public abstract class AbstractProductB {   
     //每个产品共有的方法
     public void shareMethod(){
         System.out.println("B类共有方法!");
     }
     //每个产品相同方法,不同实现
     public abstract void doSomething();
}

产品B1的实现类

public class ProductB1 extends AbstractProductB {
     public void doSomething() {
             System.out.println("产品B1的实现方法");
     }
}

产品B2的实现类

public class ProductB2 extends AbstractProductB {
     public void doSomething() {
             System.out.println("产品B2的实现方法");
     }
}

抽象工厂类

public abstract class AbstractCreator {
     //创建A产品家族
     public abstract AbstractProductA createProductA(); 
     //创建B产品家族
     public abstract AbstractProductB createProductB();
}

产品等级1的实现类

public class Creator1 extends AbstractCreator {    
     //只生产产品等级为1的A产品
     public AbstractProductA createProductA() { 
             return new ProductA1();
     }
     //只生产产品等级为1的B产品
     public AbstractProductB createProductB() {
             return new ProductB1();
     }
}

产品等级2的实现类

public class Creator2 extends AbstractCreator {    
     //只生产产品等级为2的A产品
     public AbstractProductA createProductA() { 
             return new ProductA2();
     }
     //只生产产品等级为2的B产品
     public AbstractProductB createProductB() {
             return new ProductB2();
     }
}

场景类

public class Client {
     public static void main(String[] args) {
             //定义出两个工厂
             AbstractCreator creator1 = new Creator1();
             AbstractCreator creator2 = new Creator2();
             //产生A1对象
             AbstractProductA a1 =  creator1.createProductA();
             //产生A2对象
             AbstractProductA a2 = creator2.createProductA();
             //产生B1对象
             AbstractProductB b1 = creator1.createProductB();
             //产生B2对象
             AbstractProductB b2 = creator2.createProductB();

            a1.doSomething();

            a2.doSomething();

            b1.doSomething();

            b2.shareMethod();
     }
}

总结

抽象工厂作为设计模式中较为简单的模式,与之前两种模式(SingletonPattern、FactoryMethodPattern)同样有非常多的使用场景。一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;系统中有多于一个的产品族,而每次只使用其中某一产品族;属于同一个产品族的产品将在一起使用;系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

在很多软件系统中需要更换界面主题,要求界面中的按钮、文本框、背景色等一起发生改变时,可以使用抽象工厂模式进行设计。

参考

设计模式
设计模式之禅
3. 抽象工厂模式(Abstract Factory) — Graphic Design Patterns

sev7e0
Write by sev7e0
end
本文目录