Abstract Factory 抽象工厂——对象创建型模式
1. 意图
提供一个接口以创建一系列相关或相互依赖的对象,而无需指定它们具体的类。
2. 动机
考虑一个支持多种视感(look-and-feel)标准的用户界面工具包,不同的视感风格为诸如滚动条、窗口和按钮等用户界面“窗口组件”定义不同的外观和行为。为保证视感风格标准之间的可移植性,一个应用不应该为一个特定的视感外观硬编码它的窗口组件。在整个应用实例化特定视感风格的窗口组件类将使得以后很难改变视感风格。
为解决这一问题,我们可以定义一个抽象的WidgetFactory类,这个类声明了一个创建每一类基本窗口组件的接口。每一类窗口组件都有一个抽象类,而具体子类则实现了窗口组件的特定视感风格。
3. 适用性
在以下情况下使用Abstract Factory
- 一个系统要独立于它的产品的创建、组合和表示。
- 一个系统要由多个产品系列中的一个来配置。
- 要强调一系列相关的产品对象的设计以便进行联合使用。
- 提供一个产品类库,但只想显示它们的接口而不是实现。
4. 结构
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
|
#include <iostream>
#ifndef CREATIONPATTERNDESIGN_ABSTRACTFACTORY_H #define CREATIONPATTERNDESIGN_ABSTRACTFACTORY_H
using namespace std;
void test_abstract_factory();
class Window { public: virtual void show() { cout << "这是一个普通窗口" << endl; } };
class MacWindow : public Window{ public: virtual void show() { cout << "这是一个 mac 风格的窗口" << endl; } };
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; } };
class WidgetFactory { public: virtual std::shared_ptr<ScrollBar> create_scrollbar() = 0; virtual std::shared_ptr<Window> create_window() = 0; };
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>(); } };
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
|
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
|
#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)。