0%

设计模式-创建型-工厂方法

工厂方法是一种创建型设计模式,是基于简单工厂的改进

意图

简单工厂中,一个工厂类统一实例化所有的产品,而工厂方法,每个产品用特定的工厂子类实例化。定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。

和简单工厂对比

在简单工厂方法中,同一接口的不同产品对象都由一个工厂创建出来。这种做法存在两个问题:

  • 当产品对象很多时,工厂就会成为一个“过大类”
  • 当新增产品对象时,需要在工厂中增加一个分支。这就违反了“开闭原则”

第一条很好理解,一个工厂负责生产所有的产品,不断增加产品的种类,工厂中的 if 语句也就越多。同时,由于增加一个新的产品种类,就要修改工厂的代码,因此违反了开闭原则,开闭原则希望当增加新功能时不用修改原有的代码,只用通过新增代码就完成。

所以工厂方法,特定的 产品使用特定的 工厂方法生产,当新增一个方法时,只用新增一个生产它的工厂子类即可。因此针对产品不会频繁变化,且产品种类较少的情景下 使用简单工厂反而好些。

实现

从代码可以看出实现的核心是:

  • 不同子类重写不同的new 产品的函数,主工厂中首先调用 获取产品的函数获取产品,再执行功能。
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
// 产品抽象
class Product {
public:
virtual ~Product() {}
virtual std::string Operation() const = 0;
};
// 子类产品1
class ConcreteProduct1 : public Product {
public:
std::string Operation() const override {
return "{Result of the ConcreteProduct1}";
}
};
// 子类产品2
class ConcreteProduct2 : public Product {
public:
std::string Operation() const override {
return "{Result of the ConcreteProduct2}";
}
};

// 工厂主类
class Creator {
public:
virtual ~Creator(){};
virtual Product* FactoryMethod() const = 0;

std::string SomeOperation() const {
// 在工厂主类中 生产 产品,FactoryMethod 是由对应的子类重写了,因此不同的子类会返回不同的产品
// 然后再 调用产品完成特定的功能
Product* product = this->FactoryMethod();

std::string result = "Creator: The same creator's code has just worked with " + product->Operation();
delete product;
return result;
}
};

// 工厂1 用于生产产品1
class ConcreteCreator1 : public Creator {
public:
Product* FactoryMethod() const override {
return new ConcreteProduct1();
}
};
// 工厂2 用于生产产品2
class ConcreteCreator2 : public Creator {
public:
Product* FactoryMethod() const override {
return new ConcreteProduct2();
}
};


void ClientCode(const Creator& creator) {
// ...
std::cout << "Client: I'm not aware of the creator's class, but it still works.\n"
<< creator.SomeOperation() << std::endl;
// ...
}

int main() {
std::cout << "App: Launched with the ConcreteCreator1.\n";
Creator* creator = new ConcreteCreator1();
ClientCode(*creator);
std::cout << std::endl;
std::cout << "App: Launched with the ConcreteCreator2.\n";
Creator* creator2 = new ConcreteCreator2();
ClientCode(*creator2);

delete creator;
delete creator2;
return 0;
}