0%

设计模式:工厂模式

引言:本文主要介绍c++工厂模式,从低级到高级的逐步严谨。

介绍

工厂模式:这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

本文主要介绍五种工厂模式:简单工厂模式,工厂方法模式,抽象工厂模式,工厂模板模式,注册模板类+单例工厂模式,其设计思路以及兼容性、拓展性逐步递进。

简单工厂模式

简单工厂模式由工厂类,抽象产品类,具体产品类组成,简单工厂模式的工厂类中封装了创建具体产品对象的函数。以Shoes类为例进行说明

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
// 抽象产品类
class Shoes {
public:
virtual ~Shoes(){}
virtual void show() = 0;
};

// Nike鞋子类
class NikeShoes : public Shoes {
public:
void show() {
std::cout << "Nike!" << std::endl;
}
};

// Adidas鞋子类
class AdidasShoes : public Shoes {
public:
void show() {
std::cout << "Adidas!" << std::endl;
}
};

// 工厂类
class ShoesFactory {
public:
enum class SHOESTYPE {
NIKE,
ADIDAS,
};

Shoes* createShoes(SHOESTYPE type){
switch (type) {
case NIKE:
return new NikeShoes;
break;
case ADIDAS:
return new AdidasShoes;
break;
default:
return nullptr;
break;
}
}
};

// main函数
int main() {
ShoesFactory factory;
Shoes* pNikeShoes = factory.createShoes(ShoesFactory::SHOESTYPE::NIKE);
pNikeShoes->show();
Shoes* pAdidasShoes = factory.createShoes(ShoesFactory::SHOESTYPE::ADIDAS);
pAdidasShoes->show();

delete pNikeShoes;
delete pAdidasShoes;
}

这种简单工厂模式的扩展性非常差,新增产品类的时候,需要去修改工厂类

工厂方法模式

工厂方法模式是用多个工厂去生产多个产品,每个工厂只负责生产对应的产品。由抽象工厂类,具体工行类,抽象产品类,具体产品类组成。

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
// 抽象产品类
class Shoes {
public:
virtual ~Shoes(){}
virtual void show() = 0;
};

// Nike鞋子类
class NikeShoes : public Shoes {
public:
void show() {
std::cout << "Nike!" << std::endl;
}
};

// Adidas鞋子类
class AdidasShoes : public Shoes {
public:
void show() {
std::cout << "Adidas!" << std::endl;
}
};

// 抽象工厂
class ShoesFactory {
public:
virtual Shoes* createShoes() = 0;
virtual ~ShoesFactory(){};
};

// Nike生产工厂
class NikeProducer : public ShoesFactory {
public:
Shoes* createShoes() {
return new NiKeShoes();
}
};

// Adidas生产工厂
class AdidasProducer : public ShoesFactory {
public:
Shoes* createShoes() {
return new AdidasShoes();
}
};

// main函数
int main() {
ShoesFactory* nikeProducer = new NikeProducer;
Shoes* pNikeShoes = nikeProducer->createShoes;
pNikeShoes->show();

ShoesFactory* adidasProducer = new AdidasProducer;
Shoes* pAdidasShoes = adidasProducer->createShoes;
pAdidasShoes->show();

delete pNikeShoes;
delete pAdidasShoes;

delete nikeProducer;
delete adidasProducer;
}

工厂方法模式每新增一个产品,虽然不需要去改变已有的工厂类,但是需要新增新产品的具体工厂类,而且一个工厂只能生产一个产品。

抽象工厂模式

抽象工厂模式解决了工厂方法模式只能生产一个产品的缺点,比如想要除了Shoes要生产,还有Clothes要生产

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
// Clothes基类
class Clothes {
public:
virtual ~Clothes() {}
virtual void show() = 0;
};

// Shoes基类
class Shoes {
public:
virtual ~Shoes() {}
virtual void show() = 0;
};


// Nike Clothes
class NikeClothes : public Clothes{
public:
void show() {
std::cout << "NikeClothes!" <<std::endl;
}
};

// Nike Shoes
class NikeShoes : public Shoes{
public:
void show() {
std::cout << "NikeShoes!" << std::endl;
}
};

// 工厂基类
class Factory {
public:
virtual ~Factory() {}
virtual Shoes* createShoes() = 0;
virtual Clothes* createClothes() = 0;
};

// Nike工厂
class NikeProducer : public Factory {
Shoes* createShoes() {
return new NikeShoes;
}

Clothes* createClothes() {
return new NikeClothes;
}
};

抽象工厂模式虽然一个工厂能生产多个产品,但是还是受到新增产品的限制, 拓展性依旧很差。需要一个封装性非常强的工厂类,在新增产品时,既不需要新增工厂类,也不需要对原有的工厂类进行修改。

模板工厂模式

抽象类只需要给出相应的接口,在具体工厂类中根据传入的模板参数实现具体生产

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
class Shoes {
public:
virtual void show() = 0;
virtual ~Shoes() {}
};

class NikeShoes : public Shoes {
public:
void show() {
std::cout << "NikeShoes!" << std::endl;
}
};

class AdidasShoes : public Shoes {
public:
void show() {
std::cout << "AdidasShoes!" << std::endl;
}
};

class Clothes {
public:
virtual void show() = 0;
virtual ~Clothes() {}
};

class NikeClothes : public Clothes {
public:
void show() {
std::cout << "NikeClothes!" << std::endl;
}
};

class AdidasClothes : public Clothes {
public:
void show() {
std::cout << "AdidasClothes!" << std::endl;
}
};

// 抽象模板工厂类定义抽象产品类的生产接口
template <class AbstractProduct>
class AbstractFacory() {
public:
virtual ~AbstractFacory() {}
virtual AbstractProduct* createProduct() = 0;
};

// 具体模板工厂类实现抽象工厂类中的接口
template <class AbstractProduct, class ConcreteProduct>
class ConcreteFactory() : public AbstractFacory<AbstractProduct> {
public:
AbstractProduct* createProduct() {
return new ConcreteProduct;
}
};

// main函数
int main() {
ConcreteFactory<Shoes, NikeShoes> nikeFactory;
Shoes* pNikShoes = nikeFactory.createProduct();
pNikeShoe->show();

delete pNikShoes;
}

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

上面的模板工厂模式实现虽然在扩展性上有了极大提升,新增产品时不在需要对工厂类进行增加或者修改,但是缺少一个可以统一随时随地获取指定产品对象的类。可以把注册的对象用一个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
// 产品注册抽象类,提供创建产品对象的接口
template <class ProductType>
class IProductRegister {
public:
virtual ProductType *CreateProduct() = 0;
protected:
IProductRegister(){}
virtual ~IProductRegister() {}
private:
IProductRegister(const IProductRegister&);
IProductRegister& operator=(const IProductRegister&);
};

// 工厂模板类,有一个map,用于保存注册和查询获取产品对象
template <class ProductType>
class ProductFactory {
public:
// 工厂是唯一的,设计为单例(非线程安全)
static ProductFactory<ProductType> &Instance() {
static ProductFactory<ProductType> instance;
return instance;
}

// 产品注册
void RegisterProduct(IProductRegister<ProductType> *register, std::string name){
m_ProductRegistry[name] = register;
}

// 根据名字,获取具体的产品对象
ProductType* GetProduct(std::string name){
if (m_ProductRegistry.find(name)!=m_ProductRegistry.end()){
return m_ProductRegistry[name]->CreateProduct();
}

// 未注册产品时,报错未找到
std::cout << "No found " << name << std::endl;
return nullptr;
}


private:
// 禁止外部构造和虚构
ProductFactory() {}
~ProductFactory() {}

// 禁止外部拷贝和赋值操作
ProductFactory(const ProductFactory &);
const ProductFactory &operator=(const ProductFactory &);

// 保存注册过的产品,key:产品名字 , value:产品类型
std::map<std::string, IProductRegister<ProductType>*> m_ProductRegistry;
};

// 产品注册模板类,用于创建具体产品和向工厂里注册产品
template <class ProductType, class ProductImpl>
class ProductRegistrar : public IProductRegistrar<ProductType> {
explicit ProductRegistrar(std::string name) {
// 注册
ProductFactory<ProductType>::Instance.RegisterProduct(this, name);
}

// 创建具体产品对象指针
ProductType *CreateProduct(){
return new ProductImpl;
}
};


// main函数
int main() {
//注册
ProductRegistrar<Shoes, NiKeShoes> nikeShoes("nike");
//获取
Shoes* pNikeShoes = ProductFactory<Shoes>::Instance.GetProduct("nike");
pNikeShoes->show();
delete pNikeShoes;
}