間接的“美”
中國人是一個(gè)含蓄的民族,講究微妙和間接的交流方式。對象間的間接通信也同樣是面向?qū)ο笤O(shè)計(jì)中一條重要的審美觀榄融。間接性的通信可以給出較低的耦合關(guān)系,較強(qiáng)的合作關(guān)系救湖,以及微妙的結(jié)構(gòu)和易于復(fù)用的設(shè)計(jì)架構(gòu)愧杯。
----<<Java與模式>>
1.引言
定義
代理模式的英文叫Proxy或Surrogate。所謂代理就是指一個(gè)人或者一個(gè)機(jī)構(gòu)代表另一個(gè)人或另一個(gè)機(jī)構(gòu)采取行動(dòng)鞋既。在一些情況下力九,一個(gè)客戶不想或者不能直接引用一個(gè)對象憔维,而代理對象可以在客戶端和目標(biāo)對象之間起到中介作用。
意圖
為其他對象提供一種代理以控制對這個(gè)對象的訪問畏邢。
2.代理模式的分類
按職責(zé)來劃分,通常有以下使用場景:
1检吆、遠(yuǎn)程代理 :為一個(gè)位于不同地址空間的對象提供一個(gè)局域代表對象舒萎。這個(gè)不同的地址空間可以在本機(jī)上,也可以在另一臺(tái)機(jī)器中蹭沛,遠(yuǎn)程代理又叫“大使”(Ambassaor)臂寝。
2、虛擬代理 :根據(jù)需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對象摊灭,使得此對象只在需要時(shí)被創(chuàng)建咆贬。
3、Copy-on-Write 代理 :虛擬代理的一種帚呼。把復(fù)制(克绿投小)拖延到只有在客戶端需要時(shí)才啟動(dòng)。
4煤杀、保護(hù)(Protect or Access)代理 :控制對一個(gè)對象的訪問眷蜈,如果有需要,可以給不同用戶提供不同的使用權(quán)限沈自。
5酌儒、Cache代理:為某一個(gè)目標(biāo)的操作結(jié)果提供臨時(shí)的儲(chǔ)存空間,以便多個(gè)客戶端可以共享這個(gè)結(jié)果枯途。
6忌怎、防火墻(Firewall)代理:保護(hù)目標(biāo),不讓惡意用戶接近酪夷。
7榴啸、同步化(Synchronization)代理 :使幾個(gè)用戶在同時(shí)使用一個(gè)對象而沒有沖突。
8晚岭、智能引用(Smart Reference)代理:當(dāng)一個(gè)對象被引用時(shí)插掂,提供一些額外的操作,比如記錄此對象被調(diào)用的次數(shù)腥例。
3.代理模式的結(jié)構(gòu)
代理模式涉及的角色有:
- 抽象主題角色:聲明了真實(shí)主題和代理主題的共同接口辅甥。這樣一來任何使用真實(shí)主題的地方都可以使用代理主題。
- 代理主題(Proxy)角色:代理主題角色內(nèi)部含有一個(gè)對真實(shí)主題角色的引用燎竖。從而可以在任何時(shí)候操作真實(shí)主體對象璃弄;代理主題角色提供一個(gè)與真實(shí)主題角色相同的接口,以便在任何時(shí)候都可以代替真實(shí)主題构回;控制對真實(shí)主題的引用夏块,負(fù)責(zé)在需要的時(shí)候創(chuàng)建真實(shí)主題對象(或刪除真實(shí)主題對象)疏咐;代理主題通常在客戶端調(diào)用真實(shí)主題之前或之后都要執(zhí)行某個(gè)操作,而不是單純將調(diào)用傳給真實(shí)主題脐供。
-
真實(shí)主題角色:定義了代理角色所代表的的真實(shí)對象浑塞。
實(shí)現(xiàn)的類圖如下圖所示:
4.代理模式的時(shí)序
靜態(tài)的類圖不適合反映模式在運(yùn)行時(shí)的特性,時(shí)序圖則更為形象政己,下圖是代理模式的時(shí)序圖表示:5.靜態(tài)代理
(1) 靜態(tài)代理
由程序員創(chuàng)建或特定工具自動(dòng)生成源代碼酌壕,也就是在編譯時(shí)就已經(jīng)將接口,被代理類歇由,代理類等確定下來卵牍。在程序運(yùn)行之前,代理類的.class文件就已經(jīng)生成沦泌。
(2) 靜態(tài)代理簡單實(shí)現(xiàn)
根據(jù)上面代理模式的類圖糊昙,來寫一個(gè)簡單的靜態(tài)代理的例子。我這兒舉一個(gè)比較粗糙的例子谢谦,假如一個(gè)班的同學(xué)要向老師交班費(fèi)释牺,但是都是通過班長把自己的錢轉(zhuǎn)交給老師。這里回挽,班長就是代理學(xué)生上交班費(fèi)船侧,
班長就是學(xué)生的代理。
首先厅各,我們創(chuàng)建一個(gè)Person接口镜撩。這個(gè)接口就是學(xué)生(被代理類),和班長(代理類)的公共接口队塘,他們都有上交班費(fèi)的行為袁梗。這樣,學(xué)生上交班費(fèi)就可以讓班長來代理執(zhí)行憔古。
代碼清單一:抽象主題角色的源代碼
// 創(chuàng)建一個(gè)代理類和真實(shí)類的共同接口Person
public interface Person{
// 上交班費(fèi)
void giveMoney();
}
代碼清單二:真實(shí)主題源代碼
Student類實(shí)現(xiàn)Person接口遮怜。Student可以具體實(shí)施上交班費(fèi)的動(dòng)作。
public class Student implements Person {
public Student() {
}
@Override
public void giveMoney() {
System.out.println("上交班費(fèi)");
}
}
代碼清單三:代理主題源代碼
/**
* 學(xué)生代理類鸿市,也實(shí)現(xiàn)了Person接口锯梁,保存一個(gè)學(xué)生實(shí)體,這樣既可以代理學(xué)生產(chǎn)生行為
*/
public class StudentsProxy implements Person{
//被代理的學(xué)生
Student stu;
public StudentsProxy() {
}
//代理上交班費(fèi)焰情,調(diào)用被代理學(xué)生的上交班費(fèi)行為
public void giveMoney() {
// 調(diào)用之前進(jìn)行操作
preGive();
if(stu == null){
stu = new Student();
}
stu.giveMoney();
// 調(diào)用之后進(jìn)行操作
postGive();
}
public void preGive(){
System.out.println("Before:在give Money之前進(jìn)行一些操作");
}
public void postGive(){
System.out.println("After:在give Money之后進(jìn)行一些操作");
}
}
代碼清單四:測試源代碼
/**
* Created by yucheng on 2018/8/9.
*/
public class StudentProxyDemo {
public static void main(String[] args) {
Person p = new StudentProxy();
p.giveMoney();
}
}
輸出結(jié)果:
Before Give Money!
上交班費(fèi)陌凳!
After Give Money!
說明:
代理模式最主要的就是有一個(gè)公共接口Person,一個(gè)具體的類Student内舟,一個(gè)代理類StudentProxyDemo,代理類持有具體類的實(shí)例合敦,代為執(zhí)行具體類實(shí)例方法。
上面說到验游,代理模式就是在訪問實(shí)際對象時(shí)引入一定程度的間接性充岛,因?yàn)檫@種間接性保檐,可以附加多種用途。這里的間接性就是指不直接調(diào)用實(shí)際對象的方法崔梗,那么我們在代理過程中就可以加上一些其他用途夜只。就如這個(gè)例子里的preGive()和postGive()方法。特別是在Spring AOP編程中蒜魄。在切點(diǎn)(即一個(gè)個(gè)方法)的前后我們可以進(jìn)行一系列操作扔亥。
這一章,我們主要講述的是代理模式的基本概念权悟、思想已經(jīng)應(yīng)用之靜態(tài)代理。而下一章推盛,我將繼續(xù)代理模式之“動(dòng)態(tài)代理”的講述峦阁。敬請期待!
推薦閱讀:
設(shè)計(jì)模式--代理模式(Proxy Pattern)-動(dòng)態(tài)代理