代理模式的定義:
由於某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象作爲訪問對象和目標對象之間的中介。例如,買高鐵票可以通過 12306 網站或者車票代售點購買而不是去車站。如找房子可以通過房屋中介完成。
代理模式的主要優點有:
- 代理對象在客戶端與目標對象之間起到一箇中介作用和保護目標對象的作用;
- 代理對象可以擴展目標對象的功能;
- 代理對象能將客戶端與目標對象分離,在一定程度上降低了系統的耦合度,增加了程序的可擴展性
其主要缺點是:
- 代理模式會造成系統設計中類的數量增加
- 增加了系統的複雜度;
代理模式的結構
代理模式的主要角色如下。
- 抽象角色(Subject):通過接口或抽象類聲明真實角色和代理角色實現的業務方法。
- 真實角色(RealSubject):實現抽象角色接口。實現了抽象角色中的具體業務,是代理對象所代表的真實對象,是最終要引用的對象。
- 代理角色(Proxy):是真實角色的代理,實現了與真實角色相同的接口,其內部含有對真實主題的引用,它可以訪問、控制或擴展真實主題的功能。
如圖所示:
代理模式的實現
例子:一個追求者(Pursuit)在追求MM(SchoolGirl),但是因爲害羞,所以委託Proxy給MM送禮物(GiveGift接口)。追求者的業務委託Proxy實現。
追求者和Proxy都要實現的抽象角色(接口),追求者是真正實現者。
抽象角色:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:23
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public interface GiveGift {
void giveSomething();
}
真實角色追求者:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:24
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class Pursuit implements GiveGift {
public Pursuit(SchoolGirl girl) {
this.girl = girl;
}
@Override
public void giveSomething() {
System.out.println("送禮物給" + girl.getName());
}
private SchoolGirl girl;
}
代理角色Proxy:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:21
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class Proxy implements GiveGift {
public Proxy(SchoolGirl girl) {
pursuit = new Pursuit(girl);
}
@Override
public void giveSomething() {
pursuit.giveSomething();
}
private Pursuit pursuit;
}
追求的MM:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:19
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class SchoolGirl {
public SchoolGirl(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
客戶端代碼:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:28
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class MainClass {
public static void main(String[] args) {
SchoolGirl girl = new SchoolGirl("李凌君");
Proxy proxyBoy = new Proxy(girl);
proxyBoy.giveSomething();
}
}
結果:
送禮物給李凌君
代理模式使用場景
- 遠程代理,也就是爲一個對象在不同的地址空間提供局部代表。這樣可以隱藏一個對象存在於不同地址空間的事實。
- 虛擬代理,是根據需要創建開銷很大的對象。通過它來存放實例化需要很長時間的真實對象。
- 安全代理,用來控制真實對象訪問時的權限。
- 智能指引,是指當調用真實的對象時,代理處理另外一些事。