引言
“代理”这个词不陌生吧?买化妆品、买奶粉、买包包,都可以通过代理代购,甚至有专门的代购网站;或者要购置一些自己不太清楚原理好坏的物品,可以找相关代理负责帮忙购买,当然了,得支付一定费用。
在软件设计模式中,也有一种模式可以提供与代购网站类似的功能。当客户端不能或者不便直接访问一个对象时,可以通过一个称为“代理”的第三方来间接访问,这样的设计模式称为代理模式。
01
代理模式简介
代理模式在软件设计中广泛应用,而且产生的变种很多,如远程代理、虚拟代理、缓冲代理、保护代理等。
代理模式: 给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
代理模式是一种对象结构型模式,在该模式中引入了一个代理对象,在客户端和目标访问对象之间起到中介的作用。代理对象可以屏蔽或删除客户不想访问的内容和服务,也可以根据客户需求增加新的内容和服务。
02
代理模式结构
代理模式的关键是代理类(Proxy)。代理模式中引入了抽象层,客户端针对抽象层编程,这样使得客户端可以一致对待真实对象和代理对象。代理模式主要有抽象主题角色(Subject)、代理主题角色(Proxy)和真实主题角色(RealSubject)组成,其UML图如下:
在实际开发过程中,代理模式产生了很多类型:
03
代理模式代码实例
在某应用软件中需要记录业务方法的调用日志,在不修改现有业务的基础上位每个类提供一个日志记录代理类,在代理类中输出日志,例如在业务方法method()调用之前输出“方法method()被调用,调用时间为2019-10-28 07:33:30”,调用之后输出“方法method()”调用成功。在代理类中调用真实业务类的业务方法,使用代理模式设计该日志记录模块的结构。
在这个案例中,真实主题角色是真实业务类,在代理类中调用真实主题角色的method()方法。该实例的UML图如下:
声明抽象方法method():
// 抽象主题角色
class Subject
{
public:
Subject(){}
virtual void method() = 0;
};
实现具体业务方法method():
// 真实主题角色
class RealSubject :public Subject
{
public:
RealSubject(){}
void method(){
printf("调用业务方法\n");
}
};
// Log类
class Log
{
public:
Log(){}
string getTime(){
time_t t = time(NULL);
char ch[64] = { 0 };
//年-月-日 时:分:秒
strftime(ch, sizeof(ch)-1, "%Y-%m-%d %H:%M:%S", localtime(&t));
return ch;
}
};
// 代理类
class Proxy:public Subject
{
public:
Proxy(){
realSubject = new RealSubject();
log = new Log();
}
void preCallMethod(){
printf("方法method()被调用,调用时间为%s\n",log->getTime().c_str());
}
void method(){
preCallMethod();
realSubject->method();
postCallMethod();
}
void postCallMethod(){
printf("方法method()调用调用成功!\n");
}
private:
RealSubject *realSubject;
Log* log;
};
#include <iostream>
#include "ProxyPattern.h"
int main()
{
Subject *subject;
subject = new Proxy();
subject->method();
printf("\n\n");
system("pause");
return 0;
}
上述代码运行效果如下:
04
总结
优点:
缺点:
适用环境: