前言

尊重原创,本系列文本解析部分主要基于Candidate for Master’s Degree School of Computer Wuhan University的K_Eckel([email protected])《设计模式精解-GoF 23 种设计模式解析附 C++实现源码》。为了避免重造轮子,本系列博文对源码在ubuntu16.04下做了验证并上传到了gitee,再次感谢。

如有问题,可邮件联系我([email protected])并共同探讨解决方案。

目录

创建型模式(Creating Pattern)

Factory 模式 | AbstactFactory 模式 | Singleton 模式 | Builder 模式 | Prototype 模式

结构型模式(Structrual Pattern)

Bridge 模式 | Adapter 模式 | Decorator 模式 | Composite 模式 | Flyweight 模式 | Facade 模式 | Proxy 模式

行为型模式(Behavioral Pattern)

Template 模式 | Strategy 模式 | State 模式 | Observer 模式 | Memento 模式 | Mediator 模式 | Command 模式 | Visitor 模式 | Iterator 模式 | Interpreter 模式 | Chain of Responsibility 模式

Proxy 模式简介:

  在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
  在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
  主要解决在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
   比如猪八戒去找高翠兰,结果是孙悟空变的,可以这样理解:把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,猪八戒访问高翠兰的时候看不出来这个是孙悟空,所以说孙悟空是高翠兰代理类。

问题

  至少在以下集中情况下可以用 Proxy模式解决问题:

  • 创建开销大的对象时候,比如显示一幅大的图片,我们将这个创建的过程交给代理去完成,GoF称之为虚代理( Virtual Proxy);
  • 为网络上的对象创建一个局部的本地代理,比如要操作一个网络上的一个对象(网络性能不好的时候,问题尤其突出),我们将这个操纵的过程交给一个代理去完成,GoF称之为远程代理( Remote Proxy)
  • 对对象进行控制访问的时候,比如在Jive论坛中不同权限的用户(如管理员、普通用户等)将获得不同层次的操作权限,我们将这个工作交给一个代理去完成,GoF称之为保护代理( Protection Proxy)
  • 智能指针( Smart pointer),关于这个方面的内容,建议参看 Andrew Koenig的《C++沉思录》中的第5章。

模式选择

   Proxy 模式典型的结构图为:
Proxy Pattern
图 1:Proxy 模式结构示意图 1

   实际上,Proxy 模式的想法非常简单。

实现

完整代码示例( code)

   Proxy 模式完整的实现代码(所有代码采用 C++实现,并在 Visual Studio Code,Version: 1.36.1 下测试运行)。
   源码gitee地址:点击这里

代码目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Proxy> tree /F
卷 Windows 的文件夹 PATH 列表
卷序列号为 F0C5-AFA6
C:.
├─include
│ Proxy.h

└─src
a.out
main.cpp
Proxy.cpp

PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Proxy>

Proxy.h:

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
// Proxy.h

#ifndef _PROXY_H_
#define _PROXY_H_

class Subject {
private:
/* data */

protected:
Subject();

public:
virtual void Request() = 0;
virtual ~Subject();
};

class ConcreteSubject : public Subject {
private:
/* data */
public:
ConcreteSubject(/* args */);
~ConcreteSubject();
void Request();
};

class Proxy {
private:
Subject* _sub;

public:
Proxy(/* args */);
Proxy(Subject* sub);
~Proxy();
void Request();
};

#endif //~_PROXY_H_

Proxy.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Proxy.cpp

#include "../include/Proxy.h"
#include <iostream>

using namespace std;

Subject::Subject(/* args */) {}
Subject::~Subject() {}

ConcreteSubject::ConcreteSubject(/* args */) {}
ConcreteSubject::~ConcreteSubject() {}
void ConcreteSubject::Request() { printf("ConcreteSubject......request.... \n"); }

Proxy::Proxy(/* args */) {}
Proxy::Proxy(Subject* sub) { _sub = sub; }
Proxy::~Proxy() { delete _sub; }
void Proxy::Request() {
printf("Proxy request.... \n");
_sub->Request();
}

main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// main.cpp

#include <iostream>
#include "../include/Proxy.h"

using namespace std;

int main(int argc, char* argv[]) {
Subject* sub = new ConcreteSubject();
Proxy* p = new Proxy(sub);
p->Request();

return 0;
}

代码说明

  Proxy 模式的实现很简单,这里不做多余解释。
  可以看到,示例代码运行后,pRequest 请求实际上是交给了 sub 来实际执行。

编译运行结果:

1
2
3
4
5
6
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Proxy\src> g++ *.cpp -std=c++11
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Proxy\src> .\a.exe
Proxy request....
ConcreteSubject......request....
PS C:\Users\guopz\Desktop\GiteeBlog\designpatternsbycpipei\structuralPattern\Proxy\src>

讨论

  Proxy 模式最大的好处就是实现了逻辑和实现的彻底解耦。