设计模型|抽象工厂模式

Yeren Lv3

定义

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

动机

  • 在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

    为了更清晰地理解工厂方法模式,需要先引入两个概念:

    • 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
    • 产品族 :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
fig1 fig2 fig3
  • 当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
  • 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。
  • 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

设计类图

fig4

结构

  • Factory:抽象工厂,抽象工厂定义了一个接口,所有的具体工厂都必须实现此接口,这个接口包含一组方法用来生产产品。
  • ConCreteFactory:具体工厂,具体工厂实现生成不同的具体产品家族,要创建一个产品,客户端主要使用其中一个工厂而不需要实例化任何产品对象。
  • Product:抽象产品,不同的抽象产品为不同的产品家族,每一个具体的工厂都能实现一整套的产品。
  • ConcreteProduct:具体产品,对抽象产品的具体分类的实现。

样例代码

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package DesignPattern;

interface AbstructProductA{
public void operationA();
}

interface AbstructProductB{
public void operationB();
}

class ConcreteProductA1 implements AbstructProductA{
@Override
public void operationA() {
System.out.println("produce a concrete product A1");
}
}

class ConcreteProductA2 implements AbstructProductA{
@Override
public void operationA() {
System.out.println("product a concrete product A2");
}
}

class ConcreteProductB1 implements AbstructProductB{
@Override
public void operationB() {
System.out.println("product a concrete product B1");
}
}

class ConcreteProductB2 implements AbstructProductB{
@Override
public void operationB() {
System.out.println("product a concrete product B2");
}
}

interface Factory{
public AbstructProductA createProductA();
public AbstructProductB createProductB();
}

class ConcreteFactory1 implements Factory{

@Override
public AbstructProductA createProductA() {
return new ConcreteProductA1();
}

@Override
public AbstructProductB createProductB() {
return new ConcreteProductB1();
}
}

class ConcreteFactory2 implements Factory{

@Override
public AbstructProductA createProductA() {
return new ConcreteProductA2();
}

@Override
public AbstructProductB createProductB() {
return new ConcreteProductB2();
}
}

public class AbstractFactory {
public static void main(String[] args) {
Factory factory1 = new ConcreteFactory1();
AbstructProductA productA1 = factory1.createProductA();
productA1.operationA();
AbstructProductB productB1 = factory1.createProductB();
productB1.operationB();

Factory factory2 = new ConcreteFactory2();
AbstructProductA productA2 = factory2.createProductA();
productA2.operationA();
AbstructProductB productB2 = factory2.createProductB();
productB2.operationB();
}
}

总结分析

  • 抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
  • 抽象工厂模式包含四个角色:抽象工厂用于声明生成抽象产品的方法;具体工厂实现了抽象工厂声明的生成抽象产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中;抽象产品为每种产品声明接口,在抽象产品中定义了产品的抽象业务方法;具体产品定义具体工厂生产的具体产品对象,实现抽象产品接口中定义的业务方法。
  • 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。
  • 抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;主要缺点在于增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。
  • 抽象工厂模式适用情况包括:一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;系统中有多于一个的产品族,而每次只使用其中某一产品族;属于同一个产品族的产品将在一起使用;系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

补充

“开闭原则”的倾斜性

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

工厂模式的退化

  • 当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

例题

假设你正在设计一个电子设备工厂生产系统,该工厂可以生产不同种类的电子设备,包括手机和笔记本电脑。每种电子设备都有不同的品牌(Apple、Huawei等)。

使用抽象工厂模式设计一个电子设备工厂系统,使得可以根据用户需求创建不同品牌的手机和笔记本电脑。

要求:

  1. 定义一个抽象工厂接口 ElectronicDeviceFactory,其中包括创建手机和创建笔记本电脑的抽象方法。
  2. 实现具体的工厂类 AppleFactoryHuaweiFactory等,分别用于创建对应品牌的手机和笔记本电脑。
  3. 定义手机和笔记本电脑的抽象产品接口,例如 PhoneLaptop,手机接口实现makeCall功能,笔记本电脑实现run功能。
  4. 实现具体的产品类,例如 ApplePhoneHUaweiPhoneAppleLaptopHuaweiLaptop等,分别实现手机和笔记本电脑的具体功能。
  5. 编写一个客户端代码,使用抽象工厂和具体工厂来创建不同品牌的手机和笔记本电脑,并调用它们的方法展示功能。

请根据以上要求,设计出这个电子设备工厂系统的设计类图和代码实现。

设计类图

示例代码

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package DesignPattern;

// 抽象产品接口
interface Phone {
void makeCall();
}

interface Laptop {
void run();
}

// 具体产品类
class ApplePhone implements Phone {
public void makeCall() {
System.out.println("Using Apple Phone to make a call");
}
}

class HuaweiPhone implements Phone {
public void makeCall() {
System.out.println("Using Huawei Phone to make a call");
}
}

class AppleLaptop implements Laptop {
public void run() {
System.out.println("Using Apple Laptop to run");
}
}

class HuaweiLaptop implements Laptop {
public void run() {
System.out.println("Using Huawei Laptop to run");
}
}

// 抽象工厂接口
interface ElectronicDeviceFactory {
Phone createPhone();
Laptop createLaptop();
}

// 具体工厂类
class AppleFactory implements ElectronicDeviceFactory {
public Phone createPhone() {
return new ApplePhone();
}

public Laptop createLaptop() {
return new AppleLaptop();
}
}

class HuaweiFactory implements ElectronicDeviceFactory {
public Phone createPhone() {
return new HuaweiPhone();
}

public Laptop createLaptop() {
return new HuaweiLaptop();
}
}

public class AbstractFactory {
public static void main(String[] args) {
ElectronicDeviceFactory appleFactory = new AppleFactory();
Phone applePhone = appleFactory.createPhone();
Laptop appleLaptop = appleFactory.createLaptop();

ElectronicDeviceFactory huaweiFactory = new HuaweiFactory();
Phone huaweiPhone = huaweiFactory.createPhone();
Laptop huaweiLaptop = huaweiFactory.createLaptop();

// 调用产品方法展示功能
applePhone.makeCall();
appleLaptop.run();

huaweiPhone.makeCall();
huaweiLaptop.run();
}
}
  • Title: 设计模型|抽象工厂模式
  • Author: Yeren
  • Created at : 2023-08-19 00:00:00
  • Updated at : 2023-08-19 00:00:00
  • Link: https://blog.yeren.xyz/2023/08/19/DP-abstract-factory-pattern/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments