一、定义
代理模式是为其他对象提供一种代理以控制对这个对象的访问。由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
二、角色
1.subject(抽象主题角色):
真实主题与代理主题的共同接口。
2.RealSubject(真实主题角色):
定义了代理角色所代表的真实对象。
3.Proxy(代理主题角色):
含有对真实主题角色的引用,代理角色通常在将客户端调用传递给真是主题对象之前或者之后执行某些操作,而不是单纯返回真实的对象。
UML类图:
三、实现
1.理论模型
#include<iostream>
using namespace std;
//抽象主题
class Object{
public:
virtual void request() = 0;
};
//真是主题
class RealObject:public Object{
public:
void request(){
cout<<"真实主题..."<<endl;
}
};
//代理
class Proxy:public Object{
public:
void request(){
if(realObject == nullptr){
realObject = new RealObject;
}
preRequest();
realObject->request();
postRequest();
}
private:
RealObject *realObject;
void preRequest(){
cout<<"访问真实主题前的处理"<<endl;
}
void postRequest(){
cout<<"访问真实主题后的处理"<<endl;
}
};
int main(){
Proxy *proxy = new Proxy;
proxy->request();
delete proxy;
return 0;
}
输出:
访问真实主题前的处理
真实主题...
访问真实主题后的处理
2.应用实例
#include<iostream>
using namespace std;
class Object{
public:
virtual void saleBook() = 0;
};
//书店实体
class BookStore:public Object{
public:
void saleBook(){
printf("实体书店价格:%d 元\n",m_price);
}
int getPrice(){
return this->m_price;
}
void setPrice(int price){
this->m_price = price;
}
private:
int m_price;
};
//淘宝代理商
class TaobaoProxy:public Object{
public:
void saleBook(){
//打折
this->m_bookStore->setPrice(this->m_bookStore->getPrice() * 0.688);
printf("淘宝打折价格:%d 元\n",this->m_bookStore->getPrice());
}
void setObject(BookStore * bookStore){
if(bookStore == nullptr)
exit(-1);
this->m_bookStore = bookStore;
}
private:
BookStore * m_bookStore;
};
//京东代理商
class JindDongProxy:public Object{
public:
void saleBook(){
this->m_bookStore->setPrice(this->m_bookStore->getPrice() * 0.88);
printf("京东打折价格:%d 元\n",this->m_bookStore->getPrice());
}
void setObject(BookStore * bookStore){
if(bookStore == nullptr)
exit(-1);
this->m_bookStore = bookStore;
}
private:
BookStore * m_bookStore;
};
int main(){
//创建实体
BookStore *bookStore = new BookStore();
bookStore->setPrice(100);
bookStore->saleBook();
//创建代理商
JindDongProxy * jingDong = new JindDongProxy;
jingDong->setObject(bookStore);
jingDong->saleBook();
TaobaoProxy * taobao = new TaobaoProxy;
taobao->setObject(bookStore);
taobao->saleBook();
delete taobao;
delete jingDong;
delete bookStore;
return 0 ;
}
输出:
实体书店价格:100 元
京东打折价格:88 元
淘宝打折价格:60 元
四、优缺点
主要优点:
1.代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
2.代理对象可以扩展目标对象的功能;
3.代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;
主要缺点:
1.在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
2.增加了系统的复杂度;
五、应用场景
1.购买火车票不一定要去火车站买,可以通过 12306 网站或者去火车票代售点买。如12306、铁友等。
2.实体书店卖书,可以用淘宝、京东等电子商务平台进行代理销售。
3.远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
4.虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
5.安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
6.智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。
7.延迟加载,指为了提高系统的性能,延迟对目标的加载。例如,Hibernate 中就存在属性的延迟加载和关联表的延时加载。
注意事项:
1.和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2.和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。