代理模式是指,為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶類和目標(biāo)對象之間起到中介的作用。 百度百科《代理模式》 |
換句話說,使用代理對象,是為了在不修改目標(biāo)對象的基礎(chǔ)上,增強(qiáng)主業(yè)務(wù)邏輯。
客戶類真正的想要訪問的對象是目標(biāo)對象,但客戶類真正可以訪問的對象是代理對象。客戶類對目標(biāo)對象的訪問是通過訪問代理對象來實現(xiàn)的。當(dāng)然,代理類與目標(biāo)類要實現(xiàn)同一個接口。
例如: 有A,B,C三個類, A原來可以調(diào)用C類的方法, 現(xiàn)在因為某種原因C類不允許A類調(diào)用其方法,但B類可以調(diào)用C類的方法。A類通過B類調(diào)用C類的方法。這里B是C的代理。 A通過代理B訪問C.
原來的訪問關(guān)系:
通過代理的訪問關(guān)系:
Window系統(tǒng)的快捷方式也是一種代理模式。快捷方式代理的是真實的程序,雙擊快捷方式是啟動它代表的程序。
在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設(shè)計模式屬于結(jié)構(gòu)型模式。
在代理模式中,我們創(chuàng)建具有現(xiàn)有對象的對象,以便向外界提供功能接口。
意圖:為其他對象提供一種代理以控制對這個對象的訪問。
主要解決:在直接訪問對象時帶來的問題,比如說:要訪問的對象在遠(yuǎn)程的機(jī)器上。在面向?qū)ο笙到y(tǒng)中,有些對象由于某些原因(比如對象創(chuàng)建開銷很大,或者某些操作需要安全控制,或者需要進(jìn)程外的訪問),直接訪問會給使用者或者系統(tǒng)結(jié)構(gòu)帶來很多麻煩,我們可以在訪問此對象時加上一個對此對象的訪問層。
何時使用:想在訪問一個類時做一些控制。
如何解決:增加中間層。
關(guān)鍵代碼:實現(xiàn)與被代理類組合。
應(yīng)用實例:
⒈Windows 里面的快捷方式。
⒉豬八戒去找高翠蘭結(jié)果是孫悟空變的,可以這樣理解:把高翠蘭的外貌抽象出來,高翠蘭本人和孫悟空都實現(xiàn)了這個接口,豬八戒訪問高翠蘭的時候看不出來這個是孫悟空,所以說孫悟空是高翠蘭代理類。
⒊買火車票不一定在火車站買,也可以去代售點(diǎn)。
⒋一張支票或銀行存單是賬戶中資金的代理。支票在市場交易中用來代替現(xiàn)金,并提供對簽發(fā)人賬號上資金的控制。 5、spring aop。
優(yōu)點(diǎn):
⒈清晰。
⒉高擴(kuò)展性。
⒊智能化。
缺點(diǎn):
⒈由于在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。
⒉實現(xiàn)代理模式需要額外的工作,有些代理模式的實現(xiàn)非常復(fù)雜。
使用場景:按職責(zé)來劃分,通常有以下使用場景:
⒈遠(yuǎn)程代理。
⒉虛擬代理。
⒊Copy-on-Write 代理。
⒋保護(hù)(Protect or Access)代理。
⒌Cache代理。
⒍防火墻(Firewall)代理。
⒎同步化(Synchronization)代理。
⒏智能引用(Smart Reference)代理。
注意事項:
⒈和適配器模式的區(qū)別:適配器模式主要改變所考慮對象的接口,而代理模式不能改變所代理類的接口。
⒉和裝飾器模式的區(qū)別:裝飾器模式為了增強(qiáng)功能,而代理模式是為了加以控制。
A、 控制訪問
B、 增強(qiáng)功能
可以將代理分為兩類:靜態(tài)代理與動態(tài)代理
靜態(tài)代理和動態(tài)代理
需求:用戶需要購買u盤, u盤廠家不單獨(dú)接待零散購買,廠家規(guī)定一次最少購買1000個以上,用戶可以通過淘寶的代理商,或者微商哪里進(jìn)行購買。
淘寶上的商品,微商都是 u 盤工廠的代理商, 他們代理對u盤的銷售業(yè)務(wù)。
用戶購買-------代理商(淘寶,微商)----- u 廠家(金士頓,閃迪等不同的廠家)
設(shè)計這個業(yè)務(wù)需要的類:
1. 商家和廠家都是提供 sell 購買u盤的方法。定義購買u盤的接口 UsbSell
2. 金士頓(King)對購買1千以上的價格是 85, 3千以上是80, 5千以上是75。 單個120元。定義UsbKingFactory類,實現(xiàn)UsbSell
3. 閃迪(San)對購買1千以上的價格是 82, 3千以上是78, 5千以上是72。 單個120元。定義UsbSanFactory類,實現(xiàn)UsbSell
4. 定義淘寶的代理商 TaoBao ,實現(xiàn)UsbSell
5. 定義微商的代理商 WeiShang, 實現(xiàn)UsbSell
6. 定義測試類,測試通過淘寶, 微商購買u盤
我們將創(chuàng)建一個 Image 接口和實現(xiàn)了 Image 接口的實體類。ProxyImage 是一個代理類,減少 RealImage 對象加載的內(nèi)存占用。
ProxyPatternDemo,我們的演示類使用 ProxyImage 來獲取要加載的 Image 對象,并按照需求進(jìn)行顯示。
步驟 1
創(chuàng)建一個接口。
public interface Image {
void display();
}
步驟 2
創(chuàng)建實現(xiàn)接口的實體類。
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
public class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
步驟 3
當(dāng)被請求時,使用 ProxyImage 來獲取 RealImage 類的對象。
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 圖像將從磁盤加載
image.display();
System.out.println("");
// 圖像不需要從磁盤加載
image.display();
}
}
步驟 4
執(zhí)行程序,輸出結(jié)果:
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg