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