Java 設計模式(四)《代理模式》

lvgo發表於2018-08-23

#代理模式

更多設計模式小故事案例程式碼詳解 >>點我!點我!點我!<< 設計模式,如此簡單~


所屬型別: 結構型

標籤:

  • 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);

// 列印資訊

小明小朋友進入到了遊樂園,開始了玩耍
張三小朋友進入到了遊樂園,開始了玩耍
卿尚師小朋友進入到了遊樂園,開始了玩耍
司元慈小朋友進入到了遊樂園,開始了玩耍
馬青峰小朋友進入到了遊樂園,開始了玩耍
抱歉,今天小鬼不能夠再進去了,遊樂園要爆炸了
抱歉,今天銘三不能夠再進去了,遊樂園要爆炸了
抱歉,今天輕柳不能夠再進去了,遊樂園要爆炸了
抱歉,今天尚元慈不能夠再進去了,遊樂園要爆炸了
抱歉,今天嗯哼倉不能夠再進去了,遊樂園要爆炸了

複製程式碼

詳細程式碼點我檢視


適用場景

  • 保護代理控制對原始物件的訪問。當物件具有不同的訪問許可權時,保護代理是有用的。
  • 目標物件,建立複雜或消耗大量資源.
  • 目標物件不在本地.
  1. 遠端代理。
  2. 虛擬代理。
  3. Copy-on-Write 代理。
  4. 保護(Protect or Access)代理。
  5. Cache代理。
  6. 防火牆(Firewall)代理。
  7. 同步化(Synchronization)代理。
  8. 智慧引用(Smart Reference)代理。

注意

  1. 和介面卡模式的區別:介面卡模式主要改變所考慮物件的介面,而代理模式不能改變所代理類的介面。
  2. 和裝飾器模式的區別:裝飾器模式為了增強功能,而代理模式是為了加以控制。

優缺點

優點:

  1. 職責清晰。
  2. 高擴充套件性。
  3. 智慧化。

缺點:

  1. 由於在客戶端和真實主題之間增加了代理物件,因此有些型別的代理模式可能會造成請求的處理速度變慢。
  2. 實現代理模式需要額外的工作,有些代理模式的實現非常複雜。

相關教程


詳細演示文件


實際應用


參考文獻

相關文章