这一部分总结一下行为型设计模式中的6个,分别是:观察者模式、模板方法模式、命令模式、状态模式、职责链模式、解释器模式。
3.1 观察者模式 (Observer)
特点:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生变更时,所有依赖于它的对象都得到通知并被自动更新
应用场景:
a.当一个抽象模型由两个部分,其中一个部分依赖于另一个部分,而两者又是封装在独立的对象中时
b.当一个对象的改变需要同时改变其他对象时,但又不知道具体有多少对象需要改变时
c.当一个对象必须通知其他对象,而又不能假定其他对象是谁的时候
UML图:

实现:
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
| // 观察者模式
class Observer
{
public:
virtual void Update() = 0;
};
class Subject
{
public:
virtual void Attach(Observer *observer)
{
obs_list_.emplace_back(observer);
}
virtual void Detach(Observer *observer)
{
for(auto it = obs_list_.begin(); it != obs_list_.end();)
{
if (*it == observer)
{
it = obs_list_.erase(it);
}
else
{
it++;
}
}
}
virtual void Notify()
{
for(auto it = obs_list_.begin(); it != obs_list_.end(); it++)
{
(*it)->Update();
}
}
private:
vector<Observer *> obs_list_;
};
class ConcreteSubject:public Subject
{
public:
ConcreteSubject() = default;
string GetState() const
{
return state_;
}
void SetState(string state)
{
state_ = state;
}
private:
string state_;
};
class ConcreteObserver:public Observer
{
public:
ConcreteObserver(ConcreteSubject *subject, string name)
:subject_(subject), name_(name)
{
}
void Update() override
{
state_ = subject_->GetState();
std::cout << "observer: "<< name_.c_str() <<" state is: " << state_.c_str() << std::endl;
}
ConcreteSubject* GetSubject() const
{
return subject_;
}
void SetSubject(ConcreteSubject *subject)
{
subject_ = subject;
}
private:
string name_;
string state_;
ConcreteSubject *subject_;
};
int main()
{
ConcreteSubject *s = new ConcreteSubject();
ConcreteObserver *x = new ConcreteObserver(s, "X");
ConcreteObserver *y = new ConcreteObserver(s, "Y");
ConcreteObserver *z = new ConcreteObserver(s, "Z");
s->Attach(x);
s->Attach(y);
s->Attach(z);
s->SetState("ABC");
s->Notify();
delete s;
delete x;
delete y;
delete z;
return 0;
}
/**
* output:
observer: X state is: ABC
observer: Y state is: ABC
observer: Z state is: ABC
*/
|
优点:
- a.目标和观察者间的抽象耦合。一个目标仅知道它有一系列观察者,但是目标知道任何一个观察者属于哪一类
- b.支持“广播”式通信
缺点:
- a.意外的更新。观察者间互相之间无感知,但可能会对同一资源有依赖,目标发生更新时可能会造成错误的更新
3.2 模板方法模式 (Template method)
特点:
通过把不变行为搬移到超类,去除子类中的重复代码来体现优势
应用场景:
UML图:

实现:
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
| // 模板方法模式
class AbstractClass
{
public:
virtual void PrimitiveOpr1() = 0;
virtual void PrimitiveOpr2() = 0;
void TemplateMethod()
{
PrimitiveOpr1();
PrimitiveOpr2();
std::cout << " end " << std::endl;
}
};
class ConcreteClassA: public AbstractClass
{
public:
void PrimitiveOpr1() override
{
std::cout << "concrete class A opr 1" << std::endl;
}
void PrimitiveOpr2() override
{
std::cout << "concrete class A opr 2" << std::endl;
}
};
class ConcreteClassB: public AbstractClass
{
public:
void PrimitiveOpr1() override
{
std::cout << "concrete class B opr 1" << std::endl;
}
void PrimitiveOpr2() override
{
std::cout << "concrete class B opr 2" << std::endl;
}
};
int main()
{
AbstractClass *c;
c = new ConcreteClassA();
c->TemplateMethod();
delete c;
c = new ConcreteClassB();
c->TemplateMethod();
delete c;
}
/**
* ouput:
concrete class A opr 1
concrete class A opr 2
end
concrete class B opr 1
concrete class B opr 2
end
*/
|
优点:
缺点:
3.3 命令模式 (Command)
特点:
将一个请求封装成一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作
应用场景:
UML图:

实现:
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
| // 命令模式
class Receiver
{
public:
void Action()
{
std::cout << "action" << std::endl;
}
};
class Command
{
public:
Command(Receiver *receiver)
:receiver_(receiver)
{
}
virtual void Execute() = 0;
protected:
Receiver *receiver_;
};
class ConcreteCommand: public Command
{
public:
ConcreteCommand(Receiver *receiver)
:Command(receiver)
{}
void Execute() override
{
receiver_->Action();
}
};
class Invoker
{
public:
void SetCommand(Command *command)
{
command_ = command;
}
void ExecuteCommand()
{
command_->Execute();
}
private:
Command *command_;
};
int main()
{
Receiver *r = new Receiver();
Command *c = new ConcreteCommand(r);
Invoker *i = new Invoker();
i->SetCommand(c);
i->ExecuteCommand();
delete i;
delete c;
delete r;
}
/**
* output:
* action
*
*/
|
优点:
- a.将对象的调用者和对象的构建者进行解耦
- b.将命令操作进行对象化,这样就可以和其他对象一样被操控和扩展
- c.可将多个命令进行组合
- d.增加新的命令很容易,因为无需改变已有的类
缺点:
3.4 状态模式 (State)
特点:
主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把负责的判断逻辑简化
应用场景:
UML图:

实现:
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
| // 状态模式
class Context;
class State
{
public:
virtual void Handle(Context *context) = 0;
virtual string Name() = 0;
};
class Context
{
public:
Context(State *state)
:state_(state)
{}
void SetState(State *state)
{
state_ = state;
std::cout << "current state: "<< state_->Name() << std::endl;
}
State* GetState()
{
return state_;
}
void Request()
{
state_->Handle(this);
}
private:
State *state_;
};
class ConcreteStateB: public State
{
public:
void Handle(Context *context) override;
string Name() override;
};
class ConcreteStateA: public State
{
public:
void Handle(Context *context) override
{
if (context->GetState() != nullptr)
{
delete context->GetState();
}
context->SetState(new ConcreteStateB());
}
string Name() override
{
return "StateA";
}
};
void ConcreteStateB::Handle(Context *context)
{
if (context->GetState() != nullptr)
{
delete context->GetState();
}
context->SetState(new ConcreteStateA());
}
string ConcreteStateB::Name()
{
return "StateB";
}
int main()
{
ConcreteStateA *s = new ConcreteStateA();
Context *c = new Context(s);
c->Request();
c->Request();
c->Request();
c->Request();
if (c->GetState() != nullptr )
{
delete c->GetState();
}
delete c;
return 0;
}
/*
* output:
current state: StateB
current state: StateA
current state: StateB
current state: StateA
*/
|
优点:
- a.将与特定状态相关的行为局部化,并且将不同状态的行为分割开来
- b.使得状态转换显式化
- c.State对象可被共享
缺点:
3.5 职责链模式 (Chain of responsibility)
特点:
多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。接收者和发送者都没有对方明确的消息,且链中的对象自己也并不知道链的结构,结果是职责链可简化对象的相互连接,他们仅需要保持一个指向其后继者的引用,而不需要保持它所有的候选接收者的引用
应用场景:
UML图:

实现:
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
| // 职责链模式
class Handler
{
public:
void SetSuccessor(Handler *successor)
{
successor_ = successor;
}
virtual void HandleRequest(int request) = 0;
protected:
Handler *successor_;
string name_;
};
class ConcreteHandlerA: public Handler
{
public:
ConcreteHandlerA()
{
name_ = "HandlerA";
}
virtual void HandleRequest(int request) override
{
if (request >= 0 && request < 10)
{
std::cout << name_ << " handler " << request << std::endl;
}
else if (successor_ != nullptr)
{
successor_->HandleRequest(request);
}
}
};
class ConcreteHandlerB: public Handler
{
public:
ConcreteHandlerB()
{
name_ = "HandlerB";
}
virtual void HandleRequest(int request) override
{
if (request >= 10 && request < 20)
{
std::cout << name_ << " handler " << request << std::endl;
}
else if (successor_ != nullptr)
{
successor_->HandleRequest(request);
}
}
};
class ConcreteHandlerC: public Handler
{
public:
ConcreteHandlerC()
{
name_ = "HandlerC";
}
virtual void HandleRequest(int request) override
{
if (request >= 20 && request < 30)
{
std::cout << name_ << " handler " << request << std::endl;
}
else if (successor_ != nullptr)
{
successor_->HandleRequest(request);
}
}
};
int main()
{
Handler *h1 = new ConcreteHandlerA();
Handler *h2 = new ConcreteHandlerB();
Handler *h3 = new ConcreteHandlerC();
h1->SetSuccessor(h2);
h2->SetSuccessor(h3);
int requests[] = {2, 5, 14, 22, 18, 3, 27,20};
for(int i = 0; i < sizeof(requests)/sizeof(int); i++)
{
h1->HandleRequest(requests[i]);
}
delete h3;
delete h2;
delete h1;
return 0;
}
/*
output:
HandlerA handler 2
HandlerA handler 5
HandlerB handler 14
HandlerC handler 22
HandlerB handler 18
HandlerA handler 3
HandlerC handler 27
HandlerC handler 20
*/
|
优点:
缺点:
- a.不保证接受。可能存在没有任何一个对象处理该请求
3.6 解释器模式 (Interpreter)
特点:
如果一个特定类型的问题发生的频率足够高,那么可能就值得将问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子的问题来解决该问题。
应用场景:
a.对于复杂的文法,抽象出来的文法比较简单时
b.效率不是一个关键问题时
UML图:

实现:
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
| // 解释器模式
class PlayContext
{
public:
string GetPlayText() const
{
return text_;
}
void SetPlayText(string text)
{
text_ = text;
}
private:
string text_;
};
class Expression
{
public:
void Interpret(PlayContext * context)
{
if (context->GetPlayText() == "")
{
return;
}
else
{
string play_text = context->GetPlayText();
char key = play_text[0];
int pos1 = find_notspace(play_text, 1);
int pos2 = play_text.find(' ', pos1);
string str = play_text.substr(pos1, pos2-pos1);
double value = std::stod(str);
int next = find_notspace(play_text,pos2);
if (next != -1)
{
context->SetPlayText(play_text.substr(next, play_text.size() - next));
}
else
{
context->SetPlayText("");
}
Execute(key, value);
}
}
private:
int find_notspace(const string &str, int start = 0)
{
int i = start;
for(; i < str.size(); i++)
{
if(!isspace(str[i]))
{
return i;
}
}
return -1;
}
virtual void Execute(char key, double vlaue) = 0;
};
class Note: public Expression
{
public:
void Execute(char key, double value) override
{
string note = "";
switch (key)
{
case 'C':
note = "1 ";
break;
case 'D':
note = "2 ";
break;
case 'E':
note = "3 ";
break;
case 'F':
note = "4 ";
break;
case 'G':
note = "5 ";
break;
case 'A':
note = "6 ";
break;
case 'B':
note = "7 ";
break;
default:
break;
}
std::cout << note ;
}
};
class Scale: public Expression
{
public:
virtual void Execute(char key, double value) override
{
string scale = "";
int tmp = (int)value;
switch (tmp)
{
case 1:
scale = " low ";
break;
case 2:
scale = " mid ";
break;
case 3:
scale = " high ";
break;
default:
break;
}
std::cout << scale;
}
};
int main()
{
PlayContext *context = new PlayContext();
std::cout << "song: " << std::endl;
context->SetPlayText("O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3");
Expression *expression = nullptr;
while (context->GetPlayText().size() > 0)
{
char c = context->GetPlayText().at(0);
switch (c)
{
case 'O':
expression = new Scale();
break;
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'A':
case 'B':
case 'P':
expression = new Note();
break;
default:
break;
}
expression->Interpret(context);
delete expression;
}
std::cout << " " << std::endl;
delete context;
}
/*
output:
song:
mid 3 5 6 3 5 2 3 5 6 high 1 mid 6 5 1 3 2
*/
|
优点:
- a.易于改变和扩展文法。因为该模式使用类来表示文法规则,你可以使用继承来改变和扩展该文法
- b.易于实现文法。因为定义抽象语法树中各节点的类的实现大体类似
缺点:
- a.包含许多规则的文法难以管理和维护。文法中的每一条规则至少定义了一个类,当文法复杂时,各类就错综复杂了