这一部分总结一下行为型设计模式中的5个,分别是:中介者模式、访问者模式、策略模式、备忘录模式、迭代器模式
特点:
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
应用场景:
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
| // 中介者模式
class Country;
class UnitedNations
{
public:
virtual void Declare(string message, Country *colleague) = 0;
};
class Country
{
public:
Country(UnitedNations *mediator)
:mediator_(mediator)
{
}
protected:
UnitedNations *mediator_;
};
class USA: public Country
{
public:
USA(UnitedNations *mediator)
:Country(mediator)
{}
void Declare(string message)
{
mediator_->Declare(message, this);
}
void GetMessage(string message)
{
std::cout << "USA get message from others: " << message << std::endl;
}
};
class Iraq: Country
{
public:
Iraq(UnitedNations *mediator)
:Country(mediator)
{}
void Declare(string message)
{
mediator_->Declare(message, this);
}
void GetMessage(string message)
{
std::cout << "Iraq get message form others: " << message << std::endl;
}
};
class UnitedNationsSecurityCouncil: public UnitedNations
{
public:
void SetColleague1(USA *colleague)
{
colleague1_ = colleague;
}
void SetColleague2(Iraq *colleague)
{
colleague2_ = colleague;
}
virtual void Declare(string message, Country *colleague) override
{
if (colleague == colleague1_)
{
colleague2_->GetMessage(message);
}
else
{
colleague1_->GetMessage(message);
}
}
private:
USA *colleague1_;
Iraq *colleague2_;
};
int main()
{
UnitedNationsSecurityCouncil *UNSC = new UnitedNationsSecurityCouncil();
USA *c1 = new USA(UNSC);
Iraq *c2 = new Iraq(UNSC);
UNSC->SetColleague1(c1);
UNSC->SetColleague2(c2);
c1->Declare("dont do A action");
c2->Declare("we did not do that");
delete UNSC;
delete c1;
delete c2;
return 0;
}
/*
output:
Iraq get message form others: dont do A action
USA get message from others: we did not do that
*/
|
优点:
- a.减少了子类的生成
- b.简化了对象协议
- c.对对象如何协作进行了抽象
缺点:
- a.使控制集中化,于是就把交互复杂性变为了中介者的复杂性
4.2 访问者模式 (Visitor)
特点:
表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
应用场景:
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
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
| // 访问者模式
class ConcreteElementA;
class ConcreteElementB;
class Visitor
{
public:
virtual void VisitConcreteElementA(ConcreteElementA *a) = 0;
virtual void VisitConcreteElementB(ConcreteElementB *a) = 0;
protected:
string name_;
};
class Element
{
public:
virtual void Accept(Visitor *visitor) = 0;
string name_;
};
class ConcreteElementA:public Element
{
public:
ConcreteElementA()
{
name_ = "ConcreteElementA";
}
void Accept(Visitor *visitor)
{
visitor->VisitConcreteElementA(this);
OperationA();
}
void OperationA()
{
std::cout << "OperationA" << std::endl;
}
};
class ConcreteElementB:public Element
{
public:
ConcreteElementB()
{
name_ = "ConcreteElementB";
}
void Accept(Visitor *visitor)
{
visitor->VisitConcreteElementB(this);
OperationB();
}
void OperationB()
{
std::cout << "OperationB" << std::endl;
}
};
class ConcreteVisitor1: public Visitor
{
public:
ConcreteVisitor1()
{
name_ = "ConcreteVisitor1";
}
virtual void VisitConcreteElementA(ConcreteElementA *concreteA) override
{
std::cout << concreteA->name_ << " visit " << "ConcreteVisitor1" << std::endl;
}
virtual void VisitConcreteElementB(ConcreteElementB *concreteB) override
{
std::cout << concreteB->name_ << " visit " << "ConcreteVisitor1" << std::endl;
}
};
class ConcreteVisitor2: public Visitor
{
public:
ConcreteVisitor2()
{
name_ = "ConcreteVisitor2";
}
virtual void VisitConcreteElementA(ConcreteElementA *concreteA) override
{
std::cout << concreteA->name_ << " visit " << "ConcreteVisitor2" << std::endl;
}
virtual void VisitConcreteElementB(ConcreteElementB *concreteB) override
{
std::cout << concreteB->name_ << " visit " << "ConcreteVisitor2" << std::endl;
}
};
class ObjectStructure
{
public:
void Attach(Element *eleteme)
{
list_.push_back(eleteme);
}
void Detach(Element *element)
{
for(auto it = list_.begin(); it != list_.end(); it++)
{
if (*it == element)
{
list_.erase(it);
}
}
}
void Accept(Visitor *visitor)
{
for(auto it = list_.begin(); it != list_.end(); it ++)
{
(*it)->Accept(visitor);
}
}
private:
vector<Element*> list_;
};
int main()
{
ObjectStructure *o = new ObjectStructure();
ConcreteElementA *ea = new ConcreteElementA();
ConcreteElementB *eb = new ConcreteElementB();
o->Attach(ea);
o->Attach(eb);
ConcreteVisitor1 *v1 = new ConcreteVisitor1();
ConcreteVisitor2 *v2 = new ConcreteVisitor2();
o->Accept(v1);
o->Accept(v2);
delete v1;
delete v2;
delete ea;
delete eb;
delete o;
}
/*
output:
ConcreteElementA visit ConcreteVisitor1
OperationA
ConcreteElementB visit ConcreteVisitor1
OperationB
ConcreteElementA visit ConcreteVisitor2
OperationA
ConcreteElementB visit ConcreteVisitor2
OperationB
*/
|
优点:
- a.易于增加新的操作
- b.集中了相关的操作而分离了无关的操作
缺点:
4.3 策略模式 (Strategy)
特点:
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化
应用场景:
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
| //策略模式
class CashSuper
{
public:
virtual double AcceptCash(double money) = 0;
};
class CashContext
{
public:
CashContext(CashSuper *cspuer)
{
cs_ = cspuer;
}
void GetResult(double money)
{
double ret = cs_->AcceptCash(money);
std::cout << " total money: " << ret << std::endl;
}
private:
CashSuper *cs_;
};
class CashNormal:public CashSuper
{
public:
virtual double AcceptCash(double money)
{
std::cout << "Normal ";
return money;
}
};
class CashRebate:public CashSuper
{
public:
virtual double AcceptCash(double money)
{
double real_money = money * 0.8;
std::cout << "return: " << real_money;
return real_money;
}
};
class CashReturn:public CashSuper
{
public:
virtual double AcceptCash(double money)
{
std::cout << "rebate money: " << int(money/3);
return money;
}
};
int main()
{
CashContext *cs = nullptr;
CashNormal *n = new CashNormal();
CashRebate *rb = new CashRebate();
CashReturn *rt = new CashReturn();
cs = new CashContext(n);
cs->GetResult(600);
delete cs;
delete n;
cs = new CashContext(rb);
cs->GetResult(600);
delete cs;
delete rb;
cs = new CashContext(rt);
cs->GetResult(600);
delete cs;
delete rt;
}
/*
output:
Normal total money: 600
return: 480 total money: 480
rebate money: 200 total money: 600
*/
|
优点:
a.一个替代继承的方法
b.消除了一些条件语句
c.策略模式可以提供相同行为的不同实现
d.
缺点:
4.4 备忘录模式 (Memento)
特点:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后可将该对象恢复到原先保存的状态
应用场景:
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
| // 备忘录模式
class Memento
{
public:
Memento(string state)
:state_(state)
{}
string GetState()
{
return state_;
}
private:
string state_;
};
// 发起人
class Originator
{
public:
void SetState(string state)
{
state_ = state;
}
string GetState()
{
return state_;
}
Memento* CreateMemento()
{
return (new Memento(state_));
}
void SetMemento(Memento *memento)
{
state_ = memento->GetState();
}
void Show()
{
std::cout << "State= " << state_ << std::endl;
}
private:
string state_;
};
// 管理类
class Caretaker
{
public:
Memento *memento;
};
int main()
{
Originator *o = new Originator();
o->SetState("On");
o->Show();
Caretaker *c = new Caretaker();
c->memento = o->CreateMemento();
o->SetState("Off");
o->Show();
o->SetMemento(c->memento);
o->Show();
delete c->memento;
delete c;
delete o;
return 0;
}
/*
output:
State= On
State= Off
State= On
*/
|
优点:
缺点:
4.5 迭代器模式 (Iterator)
特点:
提供一种方法顺序访问一个聚合对象中各个元素,而不需要暴露该对象的内部表示
应用场景:
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
105
106
107
108
109
110
111
112
113
114
115
116
| // 迭代器模式
class Object
{
public:
Object(string name="object")
:name_(name)
{
}
virtual string ToStirng()
{
return name_;
};
private:
string name_;
};
template<typename T>
class List
{
};
// 迭代器抽象类
template<typename T>
class Iterator
{
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual T CurrentItem() = 0;
virtual bool IsDone() = 0;
};
// 具体的聚集类
template<typename T>
class ConcreteAggregate
{
public:
ConcreteAggregate(size_t size = 64)
:capcity_(size),current_(0),size_(0)
{
list_ = new T[size];
}
~ConcreteAggregate()
{
delete[] list_;
}
size_t Count() const
{
return size_;
}
T& Get(size_t index) const
{
return list_[index];
}
void Set(size_t index, T value)
{
if (index >= size_)
{
size_ = index + 1;
}
list_[index] = value;
}
private:
T *list_;
size_t capcity_;
size_t current_;
size_t size_;
};
template<typename T>
class ConcreteIterator: public Iterator<T>
{
public:
ConcreteIterator(const ConcreteAggregate<T> *list)
:list_(list), current_(0)
{}
virtual void First() override
{
current_ = 0;
}
virtual void Next() override
{
current_++;
}
virtual bool IsDone() override
{
return (current_ >= list_->Count());
}
virtual T CurrentItem()
{
return list_->Get(current_);
}
private:
const ConcreteAggregate<T> *list_;
size_t current_;
};
int main()
{
ConcreteAggregate<Object> *a = new ConcreteAggregate<Object>();
string strs[3] = {"zhangsan", "lisi", "wangwu"};
for(int i = 0; i < 3; i++)
{
a->Set(i, strs[i]);
}
ConcreteIterator<Object> forword(a);
for(forword.First(); !forword.IsDone(); forword.Next())
{
std::cout << "name: " << forword.CurrentItem().ToStirng() << std::endl;
}
delete a;
return 0;
}
/*
output:
name: zhangsan
name: lisi
name: wangwu
*/
|
优点:
a.它支持以不同的方法遍历一个聚合
b.简化了聚合类的接口
c.在同一个聚合类上可以有多个遍历
缺点: