设计模式(四):组合模式、责任链模式、策略模式
组合模式(Composite Pattern)
当集体对象和单一对象有功能上的相似时,使用组合模式可以为集体和单一对象提供统一的操作接口,例如文件系统,对文件夹和文件的操作,删除文件夹实际上是对文件夹中的文件进行删除;这种情况下使用组合模式有若干优点:
提供统一的操作,减少代码量;
树形的管理架构,除了文件系统,很多系统的组织与此类似,例如公司、军队等组织的管理系统;
易于扩展(开闭原则,对扩展开放,对修改封闭),一是能够容下多个层级关系,而无需每层独立一个类管理;二是添加层级和操作对象,都只要增加非叶子层级或者叶子、非叶子的操作接口即可。
组织模式将类结构组织成树形的架构,单一的对象称为叶子对象,由单一对象组成的集体对象称为组件或者容器,单一对象之下没有对象,组件对象之下可以是更细分的组件对象,也可以是某单一对象,其中抽象类定义了叶子对象和组件的类似特性,将组织架构中最大的组件定义为根,模拟一个组件模式的军队架构组织如下:
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
using namespace std;
class Interface{
public:
Interface(string& name): mName(name){};
Interface(string&& name): mName(name){};
void setParent(Interface* node){
mParent = node;
}
string getName(){
return this->mName;
}
Interface* getParent(){
return this->mParent;
}
virtual void add(Interface* node){}
virtual void remove(Interface* node){} //虚函数:叶子结点不需要,非叶子结点覆写
virtual bool hasChild(){ //虚函数:叶子结点默认,非叶子结点覆写
return false;
}
virtual void show() = 0; //纯虚函数:叶子和非叶子都必须覆写
virtual ~Interface(){}
private:
Interface* mParent = nullptr;
string mName;
};
//叶子节点:
class Leaf : public Interface{
public:
using Interface::Interface; //需显式使用基类构造
void show() override{
cout << "I belong to " << this->getParent()->getName() << " ,I am " << this->getName() << endl;
}
};
//组合节点:
class Component : public Interface{
public:
using Interface::Interface; //需显式使用基类构造
void add(Interface* node) override{
node->setParent(this);
childrenVp.push_back(node);
}
void remove(Interface* node) override{
childrenVp.erase(std::remove_if(childrenVp.begin(),childrenVp.end(),[&node](Interface* cnode){
return (cnode->getName() == node->getName());
}), childrenVp.end());
}
bool hasChild() override{
return true;
}
void show()override{
cout << "I am Captain of " << this->getName()<< ", I have "<< childrenVp.size() << " children." << endl;
}
std::vector<Interface*> getChildren(){
return this->childrenVp;
}
private:
std::vector<Interface*> childrenVp;
};
//递归释放内存
static void recurDelete(Interface* root){
if(root == nullptr)
return;
//1. 父类有虚函数,2. 指针实际为之类对象,均满足即可转换为子类指针;
Component* rt = dynamic_cast<Component*>(root);
if(rt && rt->hasChild()){
for(const auto& pos : rt->getChildren()){
recurDelete(pos);
}
}
delete root;
}
int main(){
Component* dc = new Component(string("Division")); //师
for(int i=0; i<5; i++){ //团
std::string rcName= "Regimental_" + std::to_string(i);
Component* rc = new Component(rcName);
if(i==0){ //第一团下设五个营,其他均无
for(int j=0; j<5; j++){
std::string bcName= "Battalion_" + std::to_string(j);
Leaf* lc = new Leaf(bcName);
rc->add(lc);
lc->show();
}
//For delete Test:
// Leaf* delete_lc = new Leaf(string("Battalion_2"));
// rc->remove(delete_lc);
// delete delete_lc;
}
dc->add(rc);
rc->show();
}
dc->show();
recurDelete(dc);
return 0;
}
责任链模式(Chain of Responsibility Pattern)
责任链模式是一个比较简单的模式,主要是分权和从属(上下级)关系,当需要根据权限划分上下等级可以采用该模式,客户端发起申请,高级的类处理高级请求,低级的类处理低级申请并且转发到高级类中处理业务,低级类和高级类之间通过链表结构连结,故称责任链结构。
一个例子,假设Mentor只有审批请假权限、Leader可以审批请假、加薪权限,Boss拥有全部权限,责任链实现如下:
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using namespace std;
enum class RequestType: char{Holiday, Salary, Run}; //三种权限:请假、加薪、提桶跑路
class ManagerInterface{
public:
virtual ~ManagerInterface(){}
virtual void handleRequest(RequestType request) = 0;
void setNext(ManagerInterface* next){
mNext = next;
}
protected:
ManagerInterface* mNext = nullptr;
};
class Mentor : public ManagerInterface{
public:
void handleRequest(RequestType request) override{
cout << "I am Mentor:";
switch (request)
{
case RequestType::Holiday:
cout << "同意你的请假申请,好好休息吧" << endl;
break;
case RequestType::Salary:
cout << "加薪?!同意不了一点,我得问问上级去:==>";
mNext->handleRequest(request);
break;
case RequestType::Run:
cout << "跑路?!同意不了一点,我得问问上级去:==>";
mNext->handleRequest(request);
break;
default:
break;
}
}
};
class Leader : public ManagerInterface{
public:
void handleRequest(RequestType request) override{
cout << "I am Leader:";
switch (request)
{
case RequestType::Holiday:
cout << "同意你的请假申请,这种小事以后别问我" << endl;
break;
case RequestType::Salary:
cout << "拒绝你的加薪申请,思想有错误,扣1000" << endl;
break;
case RequestType::Run:
cout << "跑路?!同意不了一点,我得问问上级去:==>";
mNext->handleRequest(request);
break;
default:
break;
}
}
};
class Boss : public ManagerInterface{
public:
void handleRequest(RequestType request) override{
cout << "I am Boss:";
switch (request)
{
case RequestType::Holiday:
cout << "同意你的请假申请,这种小事以后别问我!" << endl;
break;
case RequestType::Salary:
cout << "同意你的加薪申请,这种小事以后别问我!" << endl;
break;
case RequestType::Run:
cout << "同意你的跑路申请,你自由了!" << endl;
break;
default:
break;
}
}
};
class Client{
public:
void request(ManagerInterface*manager, RequestType request){
switch (request)
{
case RequestType::Holiday:
cout << "我想请假" << endl;
break;
case RequestType::Salary:
cout << "我想加薪" << endl;
break;
case RequestType::Run:
cout << "我想跑路" << endl;
break;
default:
break;
}
manager->handleRequest(request);
}
};
int main(){
ManagerInterface* mentor = new Mentor();
ManagerInterface* leader = new Leader();
ManagerInterface* boss = new Boss();
mentor->setNext(leader);
leader->setNext(boss);
Client* CowHorse = new Client();
cout << "Mentor, ";
CowHorse->request(mentor, RequestType::Holiday);
cout << "Mentor, ";
CowHorse->request(mentor, RequestType::Salary);
cout << "Mentor, ";
CowHorse->request(mentor, RequestType::Run);
cout << "Leader, ";
CowHorse->request(leader, RequestType::Holiday);
cout << "Leader, ";
CowHorse->request(leader, RequestType::Salary);
cout << "Leader, ";
CowHorse->request(leader, RequestType::Run);
cout << "Boss, ";
CowHorse->request(boss, RequestType::Holiday);
cout << "Boss, ";
CowHorse->request(boss, RequestType::Salary);
cout << "Boss, ";
CowHorse->request(boss, RequestType::Run);
delete mentor;
delete leader;
delete boss ;
delete CowHorse;
return 0;
}
打印输出: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Mentor, 我想请假
I am Mentor:同意你的请假申请,好好休息吧
Mentor, 我想加薪
I am Mentor:加薪?!同意不了一点,我得问问上级去:==> I am Leader:拒绝你的加薪申请,思想有错误,扣1000
Mentor, 我想跑路
I am Mentor:跑路?!同意不了一点,我得问问上级去:==> I am Leader:跑路?!同意不了一点,我得问问上级去:==>I am Boss:同意你的跑路申请,你自由了!
Leader, 我想请假
I am Leader:同意你的请假申请,这种小事以后别问我
Leader, 我想加薪
I am Leader:拒绝你的加薪申请,思想有错误,扣1000
Leader, 我想跑路
I am Leader:跑路?!同意不了一点,我得问问上级去:==> I am Boss:同意你的跑路申请,你自由了!
Boss, 我想请假
I am Boss:同意你的请假申请,这种小事以后别问我!
Boss, 我想加薪
I am Boss:同意你的加薪申请,这种小事以后别问我!
Boss, 我想跑路
I am Boss:同意你的跑路申请,你自由了!
当然也有更复杂的责任链使用双向链表或树形结构实现。
策略模式(Strategy Pattern)
假如去除责任链的上下级依赖,使得每个类相对地独立,这样体现的仅仅是分权,每一个策略对应仍然是一个类,这种模式为策略模式,一个以虚函数形式的策略模式实现如下:策略类为客户提供不同的出行策略服务,客户端根据不同的条件设置和执行策略:
1 |
|
参考链接: