1. 程式人生 > >設計模式之代理模式(Proxy Pattern)

設計模式之代理模式(Proxy Pattern)

1 代理模式定義

定義:給某個物件提供一個代理物件,並由代理物件控制對於原物件的訪問,即客戶不直接操控原物件,而是通過代理物件間接地操控原物件。

2 代理模式的作用

  • 在某些情況下,一個客戶不想或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。
  • 通過代理類對原有類進行功能增強,如增加快取、異常處理、日誌處理等,Spring AOP用的就是(動態)代理模式

3 代理模式一般涉及到的角色有:

  • 抽象主題(Subject):宣告真實物件和代理物件的共同介面;
  • 代理(Proxy):代理物件角色內部含有對真實物件的引用,從而可以操作真實物件,同時代理物件提供與真實物件相同的介面以便在任何時刻都能代替真實物件。同時,代理物件可以在執行真實物件操作時,附加其他的操作,相當於對真實物件進行封裝。
  • 真實物件(RealSubject):代理角色所代表的真實物件,是我們最終要引用的物件。

    這裡寫圖片描述

4 應用場景舉例:

下面我們就拿使用者買火車票舉一個例子,傳統的火車票購買方式就是去火車站購買,除此之外,我們還可以通過火車票代售點或者12306網站購買,其實這裡的火車票代售點就扮演著代理角色。下面我們通過程式碼演示一遍。

我們要購買火車票,就得有人賣票,我們定義一個賣票Subject

public interface TicketSubject {
   public void sell();
}

然後我們定義一個真實物件,傳統的賣票的地方是火車站:

public class TrainStation implements TicketSubject {
   public void sell() {
   System.out.println("賣出一張票!");
   }
}

最後再定義一個代理物件,火車站太遠,我們想從代售點買票,定義一個代售點做代理類:

public class TrainStationProxy implements TicketSubject {
   private TrainStation trainStation;//持有真實物件的引用
   public TrainStationProxy(TrainStation trainStation){
       this.trainStation=trainStation;
   }

  public void sell() {
      System.out.println("歡迎光臨!");
      trainStation.sell();//呼叫真實物件的方法,體現代理行為
      System.out.println("請交手續費!");
   }
}

從代理類來看,它和真實物件實現的是同一個主題介面,並且內部還持有真實物件的引用,在自己的方法內呼叫真實物件的方法,完美的進行了代理,當然代理類可以在自己的方法裡面新增一些額外的功能。

最後,我們測試一下

定義一個買票的人:

public class SomeBody {
   private TicketSubject tickSubject;
   public void buy(){
      tickSubject.sell();
   }
   public void goToTicketSubject( TicketSubject tickSubject){
      this.tickSubject=tickSubject;
   }
}

注意,買票人依賴的是介面而不是具體實現類,這樣就可以用代理類替換實際類了。

最後,這個人去代售點買票:

public class TestProxy {
   public static void main(String[] args) {
      SomeBody someBody=new SomeBody();
      TrainStationProxy adaptor=new TrainStationProxy(new TrainStation());
      someBody.goToTicketSubject(adaptor);
      someBody.buy();
   }
}

看一下列印結果:

歡迎光臨!
賣出一張票!
請交手續費!

代理類完成了購票,還增加了收取手續費的功能!