#代理模式
更多設計模式小故事案例程式碼詳解 >>點我!點我!點我!<< 設計模式,如此簡單~
所屬型別: 結構型
標籤:
- Java
- Gang Of Four
- Difficulty-Beginner (入門級難度)
注:
什麼是 GOF(四人幫,全拼 Gang of Four)?
在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名為 Design Patterns - Elements of Reusable Object-Oriented Software(中文譯名:設計模式 - 可複用的物件導向軟體元素) 的書,該書首次提到了軟體開發中設計模式的概念。 四位作者合稱 GOF(四人幫,全拼 Gang of Four)。他們所提出的設計模式主要是基於以下的物件導向設計原則。 對介面程式設計而不是對實現程式設計。 優先使用物件組合而不是繼承。
意圖
為一個類提供替代或者控制其來訪問目標類
說明
生活中的例子
週末小朋友們要去遊樂園玩耍,但是遊樂園需要買票,所以只能通過檢票口(遊樂園代理)之後才能進入,因為今天日子比較特殊,所以只有前5名小朋友才能進入,所以我們需要在檢票口對我們的遊樂園做訪問限制。
通俗來說
通過代理模式,我們可以使用一個類來表示另一個類的功能
所謂的代理者是指一個類別可以作為其它東西的介面。代理者可以作任何東西的介面:網路連線、儲存器中的大物件、檔案或其它昂貴或無法複製的資源。
程式碼實操
我們的遊樂園有一個統一的大門介面(檢票口),那有一個進入的方法,小朋友可以通過這個入口進入遊樂園
public interface TicketCheck {
void enter(Children children);
}
public class AmusementPark implements TicketCheck {
@Override
public void enter(Children children) {
System.out.println(children.getName() + "小朋友進入到了遊樂園,開始了玩耍");
}
}
複製程式碼
這是一個只有名字的簡單的小朋友類
public class Children {
private String name;
public Children(String name) {
this.name = name;
}
}
複製程式碼
然後我們通過遊樂園的代理類,來對訪問做限制
public class AmusementParkProxy implements TicketCheck {
private static int MAX_ENTER_NUM = 5;
private TicketCheck ticketCheck;
private int current;
public AmusementParkProxy(TicketCheck ticketCheck) {
this.ticketCheck = ticketCheck;
}
/**
* 定義一個進入遊樂園的方法
*
* @param children 小朋友
*/
@Override
public void enter(Children children) {
if (current < MAX_ENTER_NUM) {
ticketCheck.enter(children);
current++;
} else {
System.out.println("抱歉,今天" + children.getName() + "不能夠再進去了,遊樂園要爆炸了");
}
}
}
複製程式碼
模擬進入遊樂園情況
AmusementParkProxy amusementParkProxy = new AmusementParkProxy(new AmusementPark());
ArrayList<Children> children = new ArrayList<>();
children.add(new Children("小明"));
children.add(new Children("張三"));
children.add(new Children("卿尚師"));
children.add(new Children("司元慈"));
children.add(new Children("馬青峰"));
children.add(new Children("小鬼"));
children.add(new Children("銘三"));
children.add(new Children("輕柳"));
children.add(new Children("尚元慈"));
children.add(new Children("嗯哼倉"));
children.forEach(amusementParkProxy::enter);
// 列印資訊
小明小朋友進入到了遊樂園,開始了玩耍
張三小朋友進入到了遊樂園,開始了玩耍
卿尚師小朋友進入到了遊樂園,開始了玩耍
司元慈小朋友進入到了遊樂園,開始了玩耍
馬青峰小朋友進入到了遊樂園,開始了玩耍
抱歉,今天小鬼不能夠再進去了,遊樂園要爆炸了
抱歉,今天銘三不能夠再進去了,遊樂園要爆炸了
抱歉,今天輕柳不能夠再進去了,遊樂園要爆炸了
抱歉,今天尚元慈不能夠再進去了,遊樂園要爆炸了
抱歉,今天嗯哼倉不能夠再進去了,遊樂園要爆炸了
複製程式碼
適用場景
- 保護代理控制對原始物件的訪問。當物件具有不同的訪問許可權時,保護代理是有用的。
- 目標物件,建立複雜或消耗大量資源.
- 目標物件不在本地.
- 遠端代理。
- 虛擬代理。
- Copy-on-Write 代理。
- 保護(Protect or Access)代理。
- Cache代理。
- 防火牆(Firewall)代理。
- 同步化(Synchronization)代理。
- 智慧引用(Smart Reference)代理。
注意
- 和介面卡模式的區別:介面卡模式主要改變所考慮物件的介面,而代理模式不能改變所代理類的介面。
- 和裝飾器模式的區別:裝飾器模式為了增強功能,而代理模式是為了加以控制。
優缺點
優點:
- 職責清晰。
- 高擴充套件性。
- 智慧化。
缺點:
- 由於在客戶端和真實主題之間增加了代理物件,因此有些型別的代理模式可能會造成請求的處理速度變慢。
- 實現代理模式需要額外的工作,有些代理模式的實現非常複雜。
相關教程
詳細演示文件
實際應用
- java.lang.reflect.Proxy
- Apache Commons Proxy
- Mocking frameworks Mockito, Powermock, EasyMock
- Spring AOP