回忆上文,在工厂模式中,改进了简单工厂模式引进一个新产品就要改动核心工厂类代码的缺点。将核心工厂类变成一个抽象的工厂类,定义了产生对象的方法。具体的每个产品都需要一个产品工厂类,来继承抽象工厂,实现产品对象的创建。即每一个具体工厂都负责生产一种对应的具体产品,这些产品都属于同一大类

发现问题:我们的工厂只能创建同一大类产品? —继承同一抽象类或者实现同一接口。
解决:引入抽象工厂模式,使得工厂不单单只生产某同一大类产品,还可以生产其他大类产品。

  • 打破了工厂和具体产品的一对一关系 ——一个具体的工厂类可以生产多个大类的产品。

    1.定义 —是什么?

    抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
    在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

2.引入 —为什么?

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。

3.原理 —什么原理?

3.1抽象工厂模式角色:

  • AbstractFactory:用于声明生成抽象产品的方法
  • ConcreteFactory:实现了抽象工厂声明的生成抽象产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中;
  • AbstractProduct:为每种产品声明接口,在抽象产品中定义了产品的抽象业务方法;
  • Product:定义具体工厂生产的具体产品对象,实现抽象产品接口中定义的业务方法。

    3.2类图

    image.png
    相比于之前的生产手机的体系,有新增了一个生产口罩的体系。在抽象工厂中不单单是生产手机的方法了,还增加了生产口罩的方法,然后各个子类去实现它。则产品工厂就有了创建口罩的方法。
    抽象工厂模式只是工厂模式的一个拓展,抽象工厂模式只有一个生产体系的话,就会退回到工厂模式。二者的区别不是特别大。但是但我们去新增一个产品体系,则必须对工厂类进行修改,改动其原有的工厂逻辑。

    4.实例

    4.1案例一

    image.png

    4.2案例二

    image.png
    其中 AbstractProductA 和 AbstractProductB 就是两个产品族的抽象类 (或者接口),而 Product1 和 Product2 就是产品族下的具体产品类,AbstractCreator 就是工厂的抽象。

  • 产品族的抽象类,AbstractProductAAbstractProductB

    1. public abstract class AbstractProductA {
    2. //每个产品共有的方法
    3. public void shareMethod() {
    4. }
    5. // 每个产品相同方法,不同实现
    6. public abstract void doSomething();
    7. }
    1. public abstract class AbstractProductB {
    2. //每个产品共有的方法
    3. public void shareMethod() {
    4. }
    5. // 每个产品相同方法,不同实现
    6. public abstract void doSomething();
    7. }
  • 两个产品族的具体实现类代码,

    1. public class ProductA1 extends AbstractProductA {
    2. public void doSomething() {
    3. System.out.println("我是产品A1");
    4. }
    5. }
    1. public class ProductA2 extends AbstractProductA {
    2. public void doSomething() {
    3. System.out.println("我是产品A2");
    4. }
    5. }

    ```java public class ProductB1 extends AbstractProductB { public void doSomething() {

    1. System.out.println("我是产品B1");

    } } public class ProductB2 extends AbstractProductB { public void doSomething() {

    1. System.out.println("我是产品B2");

    } }

  1. 抽象工厂类`AbstractCreator`,有N个产品族,在抽象工厂类中就应该有N个创建方法。我们这里定义两个产品族的产品创建,代码如下:
  2. ```java
  3. public abstract class AbstractCreator {
  4. //创建A产品
  5. public abstract AbstractProductA createProductA();
  6. //创建B产品
  7. public abstract AbstractProductB createProductB();
  8. }

然后是创建产品的具体工厂,有N个产品等级就应该有N个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。

  1. public class Creator1 extends AbstractCreator {
  2. public AbstractProductA createProductA() {
  3. return new ProductA1();
  4. }
  5. public AbstractProductB createProductB() {
  6. return new ProductB1();
  7. }
  8. }
  9. public class Creator2 extends AbstractCreator {
  10. public AbstractProductA createProductA() {
  11. return new ProductA2();
  12. }
  13. public AbstractProductB createProductB() {
  14. return new ProductB2();
  15. }
  16. }
  1. public class Client {
  2. public static void main(String[] args) {
  3. //定义出两个工厂
  4. AbstractCreator creator1 = new Creator1();
  5. AbstractCreator creator2 = new Creator2();
  6. //产生A1对象
  7. AbstractProductA a1 = creator1.createProductA();
  8. //产生A2对象
  9. AbstractProductA a2 = creator2.createProductA();
  10. //产生B1对象
  11. AbstractProductB b1 = creator1.createProductB();
  12. //产生B2对象
  13. AbstractProductB b2 = creator2.createProductB();
  14. a1.doSomething();
  15. a2.doSomething();
  16. b1.doSomething();
  17. b2.doSomething();
  18. }
  19. }

运行结果:

  1. 我是产品A1
  2. 我是产品A2
  3. 我是产品B1
  4. 我是产品B2

5. 总结

总结下抽象工厂模式的特点,抽象工厂是所有形式的工厂模式中最为抽象和最具一般性的一种形态,其优缺点大致如下:
1、隔离了具体类的生成,使得客户并不需要知道什么被创建,具有良好的封装性。
2、横向扩展容易。同个产品族如果需要增加多个 产品,只需要增加新的工厂类和产品类即可。
3、纵向扩展困难。如果增加新的产品组,抽象工厂类也要添加创建该产品组的对应方法,这样一来所有的具体工厂类都要做修改了,严重违背了开闭原则。