Post

设计模式:抽象工厂模式

回顾:工厂模式

在前面的 文章 中我们提到了 工厂方法模式,子类通过实现父类提供的抽象方法来达到对象构建的差异化,外界只需要选择合适的工厂类就可以创建出对应的对象。这样的模式下,具体的工厂类和产品类均依赖于抽象,从而实现了关系逻辑的解耦。

这里也把工厂方法模式的类关系图放在下面方便回顾以及开展我们今天的话题:

从上面的关系图可以看出,这里的工厂与产品之间的关系是一对一,也就是一个工厂只负责一种产品的生产,当然了,之前的文章中我们也讨论过把多个产品的生产放到一个工厂中,但是这样的话,当每个产品的业务逻辑变得复杂的话,代码的复杂度和模块与模块之间的耦合依然会产生问题。

从现实生活中来看,很多产品本就属于一个类别,比如球鞋、拖鞋、布鞋都属于鞋,它们可以在一个工厂生产。再比如,番茄、生菜、肉饼、蛋黄酱都是组成汉堡的原材料,把它们分开了看待总觉得有点怪怪的。

今天我们想要解决的问题就是如何对工厂方法模式进行扩展,使其可以很好地对多种不同类别的对象进行构建。

抽象工厂模式

我们知道,工厂方法模式中的核心是那个抽象的工厂方法,子类通过将抽象工厂方法实现来对相对应的对象进行构建。那么有没有可能我们提供多个不同的抽象方法,每个方法包含着一种产品/对象的构建逻辑,顺着这个逻辑,我们就可以得到如下的类关系图:

同样的,我们也可以得到和工厂方法模式类似的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
abstract class Product {
  /*...*/;
}

class ProductA1 extends Product {
  /*...*/;
}

class ProductA2 extends Product {
  /*...*/;
}

class ProductB1 extends Product {
  /*...*/;
}

class ProductB2 extends Product {
  /*...*/;
}

abstract class Factory {
  protected abstract Product createProduct1(String param);
  protected abstract Product createProduct2(String param);
}

class ProductFactoryA extends Factory {
  protected Product createProduct1(String param) {
    // business logic for create productA1...

    return new productA1();
  }

  protected Product createProduct2(String param) {
    // business logic for create productA2...

    return new productA2();
  }
}

class ProductFactoryB extends Factory {
  protected Product createProduct1(String param) {
    // business logic for create productB1...

    return new productB1();
  }

  protected Product createProduct2(String param) {
    // business logic for create productB2...

    return new productB2();
  }
}

抽象工厂类囊括了多个对象的创建,通常来说这些对象都存在某种联系,要不都是某个整体的组成部分,要不就属于一个大类。抽象工厂模式的优点其实就是工厂方法模式的优点,用户端不需要知道任何的具体对象的构造细节,只需要通过工厂类的指定方法来构建所需的对象即可。

抽象工厂模式有一个美中不足的地方就是,它不对修改封闭,也就是说当有一个新的产品需要引入,那么你很可能需要去改已经存在的工厂类,你需要引入新的抽象方法。它所带来的好处就是用户可以通过一个工厂来实现多种对象的构建。

其实,不管是工厂方法模式,还是抽象工厂模式,它们都可以让具体的应用不去依赖于具体类,减少应用中的相互依赖,降低模块之间的耦合性。让我们真正地可以面向接口(抽象)编程。

This post is licensed under CC BY 4.0 by the author.