工厂模式

工厂模式分三种,从简单到复杂依次为:简单工厂模式、工厂方法模式、抽象工厂模式。

简单工厂模式结构包括:工厂类、抽象产品类和具体产品类。

以一个工厂生产各种品牌的鞋为例,工厂单开一类,内设CreateShoes()函数,函数通过switch结构根据输入的鞋子类型名决定生产哪个牌子的鞋子;鞋子作为抽象产品类,覆盖了各个具体的鞋子牌子,细分到各个牌子的鞋子的模块则为具体产品类。

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
/*简单工厂*/

/*抽象产品类和具体产品类*/
class Shoes
{

public:
/*虚析构函数,保证各个子类能正确析构*/
virtual ~Shoes() {}
/*纯虚函数,具体功能在具体的子类中定义*/
virtual void Show() = 0;
};

/*公有继承,成员函数公有*/
class NikeShoes : public Shoes
{
public:
void Show()
{
std::cout << "Nike's show" << std::endl;
}
};

class AdidasShoes : public Shoes
{
public:
void Show()
{
std::cout << "Adidas's show" << std::endl;
}
};


/*工厂类*/
enum SHOES_TYPE
{
NIKE,
ADIDAS
};

class ShoesFactory
{

public:
/*根据鞋子的类型创建对应的鞋子对象*/
Shoes* CreateShoes(SHOES_TYPE type)
{
switch (type)
{
case NIKE:
return new NikeShoes();
break;
case ADIDAS:
return new AdidasShoes();
break;
default:
return nullptr;
break;
}
}
};

void main()
{
/*简单工厂模式*/
ShoesFactory shoesFactory;

/*从工厂对象创建nike鞋对象*/
Shoes* pNikeShoes = shoesFactory.CreateShoes(NIKE);
if (pNikeShoes != nullptr)
{
pNikeShoes->Show();
/*用完释放资源*/
delete pNikeShoes;
pNikeShoes = nullptr;
}

Shoes* pAdidasShoes = shoesFactory.CreateShoes(ADIDAS);
if (pAdidasShoes != nullptr)
{
pAdidasShoes->Show();
delete pAdidasShoes;
pAdidasShoes = nullptr;
}
}

可以为各种不同牌子的鞋子开设独立的生产线,每个生产线只生产同品牌的鞋子,此时转为工厂方法模式。

工厂方法模式相比简单工厂模式,将工厂类分为抽象工厂类和具体工厂类,工厂和产品(鞋子)两块都有各自的抽象和具体。

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
class FMShoes
{

public:
virtual ~FMShoes() {}
virtual void FMShow() = 0;
};

class FMNikeShoes : public FMShoes
{
public:
void FMShow()
{
std::cout << "Nike's show" << std::endl;
}
};

class FMAdidasShoes : public FMShoes
{
public:
void FMShow()
{
std::cout << "Adidas's show" << std::endl;
}
};

class FMShoesFactory
{

public:
virtual FMShoes* FMCreateShoes() = 0;
virtual ~FMShoesFactory() {}
};

class FMNikeProducer : public FMShoesFactory
{
public:
FMShoes* FMCreateShoes()
{
return new FMNikeShoes();
}
};

class FMAdidasProducer : public FMShoesFactory
{
public:
FMShoes* FMCreateShoes()
{
return new FMAdidasShoes();
}
};

当工厂与产品的生产关系不是一对一,而变成一对多时,比如原本只生产耐克鞋子的工厂现在生产耐克的各种产品,包括鞋子,衣服等,模式从工厂方法模式变为抽象工厂模式,不过四部分结构:抽象工厂类、具体工厂类、抽象产品类、具体产品类,仍然是这四部分。

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
class AFShoes
{

public:
virtual void AFShow() = 0;
virtual ~AFShoes() {}
};

class AFNikeShoes : public AFShoes
{
public:
void AFShow()
{
std::cout << "nike shoes show" << std::endl;
}
};

class AFAdidasShoes : public AFShoes
{
public:
void AFShow()
{
std::cout << "adidas shoes show" << std::endl;
}
};

class AFClothes
{

public:
virtual ~AFClothes() {}
virtual void AFShow() = 0;
};

class AFNikeClothes : public AFClothes
{
public:
void AFShow()
{
std::cout << "nike clothes show" << std::endl;
}
};

class AFAdidasClothes : public AFClothes
{
public:
void AFShow()
{
std::cout << "adidas clothes show" << std::endl;
}
};

class AFFactory
{

public:
virtual AFShoes* AFCreateShoes() = 0;
virtual AFClothes* AFCreateClothes() = 0;
virtual ~AFFactory() {}
};

class AFNikeProducer : public AFFactory
{
public:
/*一个具体工厂管理生产多款该品牌的产品*/
AFShoes* AFCreateShoes()
{
return new AFNikeShoes();
}

AFClothes* AFCreateClothes()
{
return new AFNikeClothes();
}
};

class AFAdidasProducer : public AFFactory
{
public:
AFShoes* AFCreateShoes()
{
return new AFAdidasShoes();
}

AFClothes* AFCreateClothes()
{
return new AFAdidasClothes();
}
};

进一步提高工厂类的封装性

以上三种方式在新增产品时,总要修改工厂类或新增具体的工厂类,怎样做到新增产品时不需要修改工厂类、不需要新增具体工厂类?

使用模板工厂,将工厂方法封装成模板工厂类。

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
class TFShoes
{

public:
virtual void TFShow() = 0;
virtual ~TFShoes() {}
};

class TFNikeShoes : public TFShoes
{
public:
void TFShow()
{
std::cout << "nike shoes show" << std::endl;
}
};

class TFClothes
{

public:
virtual void TFShow() = 0;
virtual ~TFClothes() {}
};

class TFUniqloClothes : public TFClothes
{
public:
void TFShow()
{
std::cout << "uniqlo clothes show" << std::endl;
}
};

/*抽象模板工厂*/
template<class TFAbstractProduct_t>
class TFAbstractFactory
{

public:
virtual TFAbstractProduct_t* TFCreateProduct() = 0;
virtual ~TFAbstractFactory() {}
};

template<class TFAbstractProduct_t, class TFConcreteProduct_t>
class TFConcreteFactory :
public TFAbstractFactory<TFAbstractProduct_t>
{
public:
TFAbstractProduct_t* TFCreateProduct()
{
return new TFConcreteProduct_t();
}
};

void main()
{
/*模板工厂*/
/*创建nike鞋的工厂对象,这种方式是创建在栈上*/
TFConcreteFactory<TFShoes, TFNikeShoes> nikeFactory;
/*创建nike鞋对象*/
TFShoes* pNikeShoes = nikeFactory.TFCreateProduct();
pNikeShoes->TFShow();
delete pNikeShoes;
pNikeShoes = NULL;

TFConcreteFactory<TFClothes, TFUniqloClothes> uniqloFactory;
TFClothes* pUniqloClothes = uniqloFactory.TFCreateProduct();
pUniqloClothes->TFShow();
delete pUniqloClothes;
pUniqloClothes = NULL;
}

产品注册模板类+单例工厂模板类

模板工厂缺少一个可以统一随时随地获取指定的产品对象的类,解决办法是:可以把产品注册的对象用map保存,通过key-value方式获取对应的产品对象的实例。

思路:产品注册功能封装成注册模板类,注册的产品对象保存在工厂模板类的map,便于产品对象的获取。把获取产品对象的功能封装成工厂模板类,为了能随时随地获取指定的产品对象,把工厂设计成单例模式。

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class PRShoes
{
public:
virtual void PRShow() = 0;
virtual ~PRShoes() {}
};

class PRNikeShoes : public PRShoes
{
public:
void PRShow()
{
std::cout << "NikeShoes show" << std::endl;
}
};

class PRClothe
{
public:
virtual void PRShow() = 0;
virtual ~PRClothe() {}
};

class PRUniqlo : public PRClothe
{
public:
void PRShow()
{
std::cout << "UniqloClothe show" << std::endl;
}
};

/*产品注册模板接口类*/
template<class ProductType_t>
class IProductRegistrar
{
public:
/*纯虚函数,产生产品的功能在产品注册模板类中实现(这个类只是个接口类)*/
virtual ProductType_t* CreateProduct() = 0;

protected:
/*禁止外部进行构造和析构,想让子类(产品注册模板类)使用*/
IProductRegistrar() {}
virtual ~IProductRegistrar() {}

private:
/*禁止外部拷贝和赋值*/
IProductRegistrar(const IProductRegistrar&);
const IProductRegistrar& operator=(const IProductRegistrar&);
};

/*工厂模板类,用于获取和注册产品对象*/
template<class ProductType_t>
class ProductFactory
{
public:
/*工厂单例的实现是使用static搭配private的构造和析构函数*/
static ProductFactory<ProductType_t>& Instance()
{
static ProductFactory<ProductType_t> instance;
return instance;
}

/*注册产品对象,名字+注册员*/
void RegisterProduct(IProductRegistrar<ProductType_t>* registrar, std::string name)
{
m_ProductRegistry[name] = registrar;
}

/*获取产品对象,通过“名字”找到对应的“注册员”,来产生产品*/
ProductType_t* GetProduct(std::string name)
{
if(m_ProductRegistry.find(name) != m_ProductRegistry.end())
{
return m_ProductRegistry[name]->CreateProduct();
}
std::cout << "No product found for" << name << std::endl;
return NULL;
}

private:
ProductFactory() {}
~ProductFactory() {}

ProductFactory(const ProductFactory&);
const ProductFactory& operator=(const ProductFactory&);

std::map<std::string, IProductRegistrar<ProductType_t>*> m_ProductRegistry;
};

/*产品注册模板类,用于创建具体的产品和从工厂里注册产品*/
template<class ProductType_t, class ProductImpl_t>
class ProductRegistrar : public IProductRegistrar<ProductType_t>
{
public:
/*构造函数,explicit使得其只能显式调用,必须要提供name,不提供名字我怎么知道自己要注册什么产品?*/
explicit ProductRegistrar(std::string name)
{
/*用(大种类ProductType_t)相应工厂的实例去注册map*/
ProductFactory<ProductType_t>::Instance().RegisterProduct(this, name);
}
/*产生一个具体产品,返回其指针*/
ProductType_t* CreateProduct()
{
return new ProductImpl_t();
}
};

void main()
{
/*生产nike鞋的过程*/
/*注册产品的种类(大类)为PRShoes,产品(子类)为PRNikeShoes,产品名为nike(通过显式调用)*/
ProductRegistrar<PRShoes, PRNikeShoes> nikeShoes("nike");
/*从PRShoes工厂单例中获取nike产品对象*/
PRShoes* pNikeShoes = ProductFactory<PRShoes>::Instance().GetProduct("nike");
pNikeShoes->PRShow();
if(pNikeShoes)
{
delete pNikeShoes;
}
}