Abstract Factory 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。Abstract Factory 使用若干个工厂方法模式,每个工厂创建一个不同类型的对象。当创建一个工厂对象时,要决定如何使用那个工厂创建的所有对象。
适用性:1.一个系统要独立于它的产品的创建、组合和表示时。2.一个系统要由多个产品系统中的一个来配置时。3.当你要强调一系列相关的产品对象的设计以便进行联合使用时。4.当你提供一个产品类库,而只是想显示它们的接口而不是实现时。
Abstract Factory 抽象工厂模式通用结构类图如下:
协作:通常在运行时刻创建一个 ConcreteFactory 类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象、客户应使用不同的具体工厂。AbstractFactory 将产品对象的创建延迟到它的 ConcreteFactory 子类。
实现:1)将工厂做为单件,一个应用中一般每个产品系列只需要一个 ConcreteFactory 的实例。因此,工厂通常最好实现为一个 Singleton。 2)创建产品 AbstractFactory 仅声明一个创建产品的接口,真正创建产品是由 ConcreteProduct 子类实现的。最通常的办法是为每一个产品定义一个工厂方法。一个具体的工厂将为每个产品重定义该工厂方法以指定产品。虽然这样的实现很简单,但它却要求每个产品系列都要有一个新的具体工厂子类,即使这些产品系列的差别很小。 3)定义可扩展的工厂, AbstractFactory 通常为第一种它可以生产的产品定义一个操作。产品的种类被编码在操作型构中。拉架一种新的产品要求改变 AbstratFactory 的接口以及所有与它相关的类。一个更灵活但不太安全的设计是给创建对象的操作增加一个参数。该参数指定了将被创建的对象的种类。它可以是一个类标识符、一个整数、一个字符串、或其他任何可以标识这种产品的东西。
代码示例:
1: //AbstractFactory.h
2: #pragma once
3:
4: //
5: class AbstractProductA;
6: class AbstractProductB;
7:
8: class AbstractFactory
9: {
10: public:
11: virtual ~AbstractFactory(){};
12: virtual AbstractProductA* CreateProductA() = 0;
13: virtual AbstractProductB* CreateProductB() = 0;
14:
15: protected:
16: AbstractFactory(){};
17: };
18:
19: class ConcreteFactory1: public AbstractFactory
20: {
21: public:
22: ConcreteFactory1(){};
23: ~ConcreteFactory1(){};
24: AbstractProductA* CreateProductA();
25: AbstractProductB* CreateProductB();
26: };
27:
28: class ConcreteFactory2: public AbstractFactory
29: {
30: public:
31: ConcreteFactory2(){};
32: ~ConcreteFactory2(){};
33: AbstractProductA* CreateProductA();
34: AbstractProductB* CreateProductB();
35: };
1: //Product.h
2: #pragma once
3: #include "AbstractFactory.h"
4:
5: class AbstractProductA
6: {
7: public:
8: virtual ~AbstractProductA() {};
9: virtual void eat() = 0;
10: protected:
11: AbstractProductA(){};
12: };
13: class AbstractProductB
14: {
15: public:
16: virtual ~AbstractProductB(){};
17: virtual void eat() = 0;
18:
19: protected:
20: AbstractProductB(){};
21: };
22:
23: class ProductA1: public AbstractProductA
24: {
25: public:
26: ProductA1(){};
27: ~ProductA1(){};
28: virtual void eat();
29: };
30: //ProductA1, ProductA2
31: class ProductA2: public AbstractProductA
32: {
33: public:
34: ProductA2(){};
35: ~ProductA2(){};
36: virtual void eat();
37: };
38:
39: //ProductB1, ProductB2
40: class ProductB1: public AbstractProductB
41: {
42: public:
43: ProductB1(){};
44: ~ProductB1(){};
45: virtual void eat();
46: };
47: class ProductB2: public AbstractProductB
48: {
49: public:
50: ProductB2(){};
51: ~ProductB2(){};
52: virtual void eat();
53: };
54:
55: //
56: class MyProduct
57: {
58: public:
59: MyProduct(AbstractFactory* factory):
60: pF(factory),
61: pA(factory->CreateProductA()),
62: pB(factory->CreateProductB()) { }
63:
64: ~MyProduct();
65:
66: void eat();
67:
68: private:
69: AbstractFactory* pF;
70: AbstractProductA* pA;
71: AbstractProductB* pB;
72: };
1: //AbstractFactory.cpp
2: #include "AbstractFactory.h"
3: #include "Product.h"
4: #include
5:
6: using namespace std;
7:
8: //
9: AbstractProductA* ConcreteFactory1::CreateProductA(){
10: return new ProductA1();
11: }
12:
13: AbstractProductB* ConcreteFactory1::CreateProductB(){
14: return new ProductB1();
15: }
16:
17: //
18: AbstractProductA* ConcreteFactory2::CreateProductA(){
19: return new ProductA2();
20: }
21: AbstractProductB* ConcreteFactory2::CreateProductB(){
22: return new ProductB2();
23: }
1: //Product.cpp
2: #include "Product.h"
3: #include
4:
5: using namespace std;
6:
7: //
8: void ProductA1::eat(){
9: cout << "ProductA1::eat()..." << endl;
10: }
11:
12: void ProductA2::eat(){
13: cout << "ProductA2::eat()..." << endl;
14: }
15:
16: //
17: void ProductB1::eat(){
18: cout << "ProductB1::eat()..." << endl;
19: }
20: void ProductB2::eat(){
21: cout << "ProductB2::eat()..." << endl;
22: }
23:
24: //MyProduct
25: void MyProduct::eat(){
26: pA->eat();
27: pB->eat();
28: }
29: MyProduct::~MyProduct()
30: {
31: delete pF;
32: delete pA;
33: delete pB;
34: }
1: //main.cpp
2: #include "AbstractFactory.h"
3: #include "Product.h"
4: #include
5:
6: int main(int argc,char* argv[])
7: {
8: MyProduct myP1(new ConcreteFactory1);
9: myP1.eat();
10:
11: MyProduct myP2(new ConcreteFactory2);
12: myP2.eat();
13:
14: return EXIT_SUCCESS;
15: }