【设计模式】抽象工厂模式

本文最后更新于:2023年12月17日 下午

Abstract Factory 抽象工厂——对象创建型模式

1. 意图

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

2. 动机

考虑一个支持多种视感(look-and-feel)标准的用户界面工具包,不同的视感风格为诸如滚动条、窗口和按钮等用户界面“窗口组件”定义不同的外观和行为。为保证视感风格标准之间的可移植性,一个应用不应该为一个特定的视感外观硬编码它的窗口组件。在整个应用实例化特定视感风格的窗口组件类将使得以后很难改变视感风格。

为解决这一问题,我们可以定义一个抽象的WidgetFactory类,这个类声明了一个创建每一类基本窗口组件的接口。每一类窗口组件都有一个抽象类,而具体子类则实现了窗口组件的特定视感风格。

3. 适用性

在以下情况下使用Abstract Factory

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

4. 结构

UML类图示意

5. 参与者

  • AbstractFactory
    • 声明一个创建抽象产品对象的操作接口
  • ConcreteFactory
    • 实现创建具体产品对象的操作
  • AbstractProduct
    • 为一类产品对象声明一个接口
  • ConcreteProduct
    • 定义一个将被相应的具体工厂创建的产品对象
    • 实现AbstracProduct接口
  • Client
    • 仅使用由AbstractFactory 和 AbstractProduct类声明的接口

6. 协作

通常在运行时创建一个ConcreteFactory类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。

AbstractFactory将产品对象的创建延迟到它的ConcreteFactory子类。

7. 效果

AbstractFactory模式有一下优点和缺点:

  • 优点:它分离了具体的类。
  • 优点:它使得易于交换产品系列。一个具体工厂类在一个应用中仅出现一次——在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。
  • 优点:它有利于产品的一致性。当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。
  • 缺点:难以支持新种类的产品,也就是难以扩展抽象工厂以生产新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及AbstractFactory类及其所有子类的改变。

8. 示例代码

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
85
86
87
88
89
90
91
92
93
// AbstractFactory.h
// Created by 张宇轩 on 2022/4/2.
// Copyright (c) 2022 zhangyuxuan. All rights reserved.
//
#include <iostream>

#ifndef CREATIONPATTERNDESIGN_ABSTRACTFACTORY_H
#define CREATIONPATTERNDESIGN_ABSTRACTFACTORY_H

using namespace std;

/**
* @brief 定义一个生产组件的抽象工厂 WidgetFactory,派生出 Mac 和 Linux 两种风格的具体抽象工厂实现类;
* 抽象的产品类对应有 Window 窗口组件和 ScrollBar 滚动条组件
*/
void test_abstract_factory();

// 抽象产品类,窗口
class Window {
public:
virtual void show() {
cout << "这是一个普通窗口" << endl;
}
};

// 具体产品类,对应于 Mac 风格系列
class MacWindow : public Window{
public:
virtual void show() {
cout << "这是一个 mac 风格的窗口" << endl;
}
};

// 具体产品类,对应于 Linux 风格系列
class LinuxWindow : public Window{
public:
virtual void show() {
cout << "这是一个 Linux 风格的窗口" << endl;
}
};

// 抽象产品类,滚动条
class ScrollBar {
public:
virtual void scroll() {
cout << "这是一个普通滚动条" << endl;
}
};

class MacScrollBar : public ScrollBar {
public:
virtual void scroll() {
cout << "这是 Mac 风格的滚动条" << endl;
}
};

class LinuxScrollBar : public ScrollBar {
public:
virtual void scroll() {
cout << "这是 Linux 风格的滚动条" << endl;
}
};

// 抽象工厂类 AbstractFactory
class WidgetFactory {
public:
virtual std::shared_ptr<ScrollBar> create_scrollbar() = 0;
virtual std::shared_ptr<Window> create_window() = 0;
};

// 具体工厂类,用于生产 Mac 风格系列的组件
class MacWidgetFactory : public WidgetFactory {
public :
virtual std::shared_ptr<ScrollBar> create_scrollbar() {
return make_shared<MacScrollBar>();
}
virtual std::shared_ptr<Window> create_window() {
return make_shared<MacWindow>();
}
};

// 具体工厂类,用于生产 Linux 风格系列的组件
class LinuxWidgetFactory : public WidgetFactory {
public :
virtual std::shared_ptr<ScrollBar> create_scrollbar() {
return make_shared<LinuxScrollBar>();
}
virtual std::shared_ptr<Window> create_window() {
return make_shared<LinuxWindow>();
}
};

#endif //CREATIONPATTERNDESIGN_ABSTRACTFACTORY_H
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
// AbstractFactory.cpp
// Created by 张宇轩 on 2022/4/2.
// Copyright (c) 2022 zhangyuxuan. All rights reserved.
//
#include <iostream>

#include "AbstractFactory.h"

void test_abstract_factory() {
cout << "——————————开始测试抽象工厂模式——————————" << endl;

shared_ptr<WidgetFactory> wf = make_shared<MacWidgetFactory>();
shared_ptr<ScrollBar> sb = wf->create_scrollbar();
shared_ptr<Window> window = wf->create_window();
sb->scroll();
window->show();

wf = make_shared<LinuxWidgetFactory>();
sb = wf->create_scrollbar();
window = wf->create_window();
sb->scroll();
window->show();

cout << "——————————结束测试抽象工厂模式——————————" << endl;
cout << endl;
}

9. 相关模式

AbstractFactory类通常用工厂方法(Factory Method)来实现,但它们也可以用Prototype实现。

一个具体的工厂通常是一个单例(Singleton)。


【设计模式】抽象工厂模式
https://2017zhangyuxuan.github.io/2022/04/02/2022-04/2022-04-02【设计模式】抽象工厂模式/
作者
Zhang Yuxuan
发布于
2022年4月2日
许可协议