一、定義
代理模式是爲其他對象提供一種代理以控制對這個對象的訪問。由於某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象作爲訪問對象和目標對象之間的中介。
二、角色
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.和裝飾器模式的區別:裝飾器模式爲了增強功能,而代理模式是爲了加以控制。