13、代理模式(Proxy)
概念:为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。
问题:在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等)直接访问会给使用者、或者系统结构带来很多麻烦。
动机:如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
总结:为一个对象添加一个代理,在代理里边实现对该对象的控制。
代码:
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
class ISubject{
public:
virtual void process();
};
//Proxy的设计在很多时候都很复杂,基本上都是使用相应的工具进行生成
class SubjectProxy: public ISubject{
public:
virtual void process(){
//对RealSubject的一种间接访问
//....
}
};
class ClientApp{
ISubject* subject;
public:
ClientApp(){
subject=new SubjectProxy();
}
void DoTask(){
//...
subject->process();
//....
}
};
14、适配器(Adapter)
概念:将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
问题:在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。
动机:如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?
总结:使用适配器把一些旧的东西移植到新的环境中。
代码:
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
//目标接口(新接口)
class ITarget{
public:
virtual void process()=0;
};
//遗留接口(旧接口)
class IAdaptee{
public:
virtual void foo(int data)=0;
virtual int bar()=0;
};
//遗留类型
class OldClass: public IAdaptee{
//具体业务
};
//对象适配器
class Adapter: public ITarget{ //继承
protected:
IAdaptee* pAdaptee;//组合
public:
Adapter(IAdaptee* pAdaptee){
this->pAdaptee=pAdaptee;
}
virtual void process(){
int data = pAdaptee->bar();
pAdaptee->foo(data);
}
};
//另一种方法:类适配器,不太好,IAdaptee是纯虚接口没有业务,OldClass不能改变,只有坏处,没有好处
class Adapter: public ITarget, protected OldClass{ //多继承
}
int main(){
IAdaptee* pAdaptee=new OldClass();
ITarget* pTarget=new Adapter(pAdaptee);
pTarget->process();
}
// 举例:容器适配器
class stack{
deque container;
};
class queue{
deque container;
};
15、中介者模式(Mediator)
概念:用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显式的相互引用(编译时依赖 → 运行时依赖),从而使其耦合松散(管理变化)相关联交互的情况对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。
问题:在软件构建过程中,经常会出现多个对象互相关联交互的情况对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。
动机:在这种情况下,我们可使用一个“中介对象”来管理对象间的关联关系,避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化。
总结:使用一个中介者解耦系统内多个相互关联的组件。
代码:
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 Component;
class Mediator;
class Mediator {
public:
virtual void notify(Component* sender, string event) {}
virtual ~Mediator(){}
}
class Component {
protected:
Mediator* dialog;
public:
Component(Mediator* dialog): dialog(dialog){}
virtual ~Component() = default;
virtual void click {
dialog->notify(this, "click");
}
virtual void keypress() {
dialog->notify(this, "keypress");
}
}
class Button : public Component {
}
class Textbox : public Component {
}
class Checkbox : public Component {
private:
bool checked = false;
public:
void check() {
checked = !checked;
dialog->notify(this, "check");
}
void isChecked() {
return checked;
}
}
class AuthenticationDialog : public Mediator {
private:
string title;
Checkbox* loginOrRegisterChkBx;
Textbox* loginUsername, *loginPassword;
Textbox* registrationUsername, *registrationPassword, *resgistrationEmail;
Button* okBtn, *cancelBtn;
public:
AuthenticationDialog(...): ...(...) {}
void notify(Component* sender, string event) {
if (sender == loginOrRegisterChkBx && event = "check") {
if (loginOr?RegisterChkBx->isChecked) {
title = "登录";
// 显示登录表单,隐藏注册表单
} else {
title = "注册";
// 显示注册表单,隐藏登录表单
}
}
if (sender == okBtn && event == "click") {
if (loginOrRegister->isChecked) {
// 查找用户信息
if (!found)
// 在登陆字段上显示错误信息
} else {
// 完成登录
}
}
}
}
16、状态模式(State)
概念:允许一个对象在其内部状态改变时改变它的行为,从而使对象看起来似乎修改了其行为。
问题:在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
动机:如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合 ?
总结:把一个状态对应的所有操作封装成子类。
代码:
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
class NetworkState{
public:
NetworkState* pNext;
virtual void Operation1()=0;
virtual void Operation2()=0;
virtual void Operation3()=0;
virtual ~NetworkState(){}
};
class OpenState :public NetworkState{
private:
static NetworkState* m_instance;
public:
static NetworkState* getInstance(){
if (m_instance == nullptr) {
m_instance = new OpenState();
}
return m_instance;
}
void Operation1(){
//**********
pNext = CloseState::getInstance();
}
void Operation2(){
//..........
pNext = ConnectState::getInstance();
}
void Operation3(){
//$$$$$$$$$$
pNext = OpenState::getInstance();
}
};
class CloseState:public NetworkState{
//...
}
class WaitState:public NetworkState{
//...
}
class NetworkProcessor{
private:
NetworkState* pState;
public:
NetworkProcessor(NetworkState* pState){
this->pState = pState;
}
void Operation1(){
//...
pState->Operation1();
pState = pState->pNext;
//...
}
void Operation2(){
//...
pState->Operation2();
pState = pState->pNext;
//...
}
void Operation3(){
//...
pState->Operation3();
pState = pState->pNext;
//...
}
};