1. 程式人生 > >代理模式(Proxy Pattern)。

代理模式(Proxy Pattern)。

定義:

為其他物件一種代理以控制對這個物件的訪問。

代理模式也叫作委託模式,它是一項基本設計技巧,許多其他模式,如狀態模式、策略模式、訪問者模式本質上是在更特殊的場合採用了委託模式,而且在日常的應用中,代理模式提供非常好的訪問控制。在一些著名的開元然間中也經常見到他的身影,如Struts2的Form元素對映就採用了代理模式(準確的說是動態代理模式)。

通用程式碼:

抽象主題類

抽象主題類可以是抽象類也可以是介面,是一個最普通的業務型別定義,無特殊要求。

public interface Subject {

// 定義一個方法

public void request();

}

真實主題類

也叫作被委託角色,被代理角色,是業務邏輯的具體執行者。

publc class RealSubject implements Subject {

// 實現方法

public void request() {

// 業務邏輯處理

}

}

代理類

也叫作委託類、代理類。它負責對真實角色的應用,把所有抽象主題類定義的方法限制委託給真實主題角色實現,並且在真實主題角色處理完畢前後做預處理和善後處理工作。

public class Proxy implements Subject {

// 要代理哪個實現類

private Subject subject = null;

// 預設被代理類

public Proxy() {

this.subject = new Proxy();

}

// 通過建構函式傳遞代理者

public Proxy(Object... objects) {}

// 實現介面中定義的方法

public void request() {

this.before();

this.subject.request();

this.after();

}

//  預處理

public void before() {

// do Something

}

// 善後處理

public void after() {

// do Something

}

}

一個代理類可以代理多個被委託者或被代理者,因此一個代理類具體代理哪個真實主題角色,是由場景類決定的。當然,最簡單的情況就是一個主題類和一個代理類,這是最簡單的代理模式。在通常情況下,一個介面只需要一個代理類就可以了,具體代理哪個實現類由高層模組來決定,也就是在代理的建構函式中傳遞被代理類,你要代理誰就產生該代理的例項,然後把被代理者傳遞進來,該模式在實際的專案應用中使用比較廣泛。

優點:

  • 職責清晰

真實的角色就是實現實際的業務邏輯,不用關心其他非本職責的事務,通過後期的代理完成一件事務,附帶的結果就是編碼簡潔清晰。

  • 高擴充套件性

具體主題角色是隨時都會發生變化的,只要它實現了介面,甭管他如何變化,都逃不脫如來佛的手掌(介面),那我們的代理完全就可以在不做任何修改的情況下使用。

  • 智慧化

例如Struts是如何把表單元素對映到物件上的。

使用場景:

代理模式的使用場景非常多,大家可以看看Spring AOP,這是一個非常典型的動態代理。

擴充套件:

1、普通代理

普通代理是我們要知道代理的存在,然後才能訪問;

2、強制代理

強制代理是呼叫者直接呼叫真是角色,而不用關心代理是否存在,其代理的產生是由真是角色決定的。

3、代理是有個性的

4、動態代理

最佳實踐:

代理模式應用的非常廣泛,大到一個系統框架、企業平臺,小到程式碼片段、事務處理,稍不留意就用到代理模式。可能該模式是大家接觸最多的模式,而且有了AOP大家寫代理就更加簡單了,有類似Spring AOP和AspectJ這樣非常優秀的工具,拿來主義即可!不過大家可以看看原始碼,特別是除錯時,只要看到類似$Proxy()這樣的結構,你應該知道這是一個動態代理了。

程式碼案例:

遊戲者介面

public interface IGamePlayer {

// 登入遊戲

public void login(String user,String password);

// 殺怪,網路遊戲的主要特色

public void killBoss();

// 升級

public void upgrade();

}

遊戲者

public GamePlayer implements IGamePlayer {

private String name ="";

// 通過建構函式傳遞名稱

public GamePlayer(String _name) {

this.name = _name;

}

// 打怪,最期望的就是殺boss

public void killBoss() {

System.out.println(this.name +"在打怪!");

}

// 進遊戲之前你肯定要登入吧,這是一個必要條件

public void login(String user, String password) {

System.out.println("登入名為" + user + "的使用者" + this.name + "登入成功!");

}

// 升級,升級有很多方法,花錢買是一種,做任務也是一種

public void upgrade() {

System.out.println(this.name + " 又升級了!");

}

}

代練者

public class GamePlayerProxy implements IGamePlayer {

private IGamePlayer gamePlayer = null;

// 通過建構函式傳遞要對誰進行代練

public GamePlayerProxy(IGamePlayer _gamePlayer) {

this.gamePlayer = _gamePlayer;

}

// 代練殺怪

public void killBoss() {

this.gamePlayer.killBoss();

}

// 代練登入

public void login(String user, String password) {

this.gamePlayer.login(user, password);

}

}

場景類
 

public class Client {

public static void main(String[] args) {

// 定義一個痴迷的玩家

IGamePlayer player = new GamePlayer("張三");

// 然後再定義一個代練者

IGamePlayer proxy = new GamePlayerProxy(player);

// 開始打遊戲,記下時間戳

System.out.println("開始時間是:2017-01-01 23:27");

proxy.login("zhangSan","password");

// 開始殺怪

proxy.killBoss();

// 升級

proxy.upgrade();

// 記錄結束遊戲時間

System.out.println("結束時間是:2017-01-02 01:30");

}

}

普通代理的遊戲者

public class GamePlayer implements IGamePlayer {

  private String name ="";

  // 建構函式限制誰能建立物件

  public GamePlayer(IGamePlayer _gamePlayer, String _name) throws Exception {

    if(_gamePlayer == null) {

throws new Exception("不能建立真實角色!");

    } else {

this.name = _name;

    }

  }

// 打怪,最期望的就是殺老怪

public void killBoss() {

System.out.println(this.name +"在打怪!");

}

// 進遊戲之前你肯定要登入吧,這是一個必要條件

public void login(String user, String password) {

System.out.println("登陸名為" + user + "的使用者" + this.name + "登入成功!");

}

// 升級,升級有很多方法,花錢買也是一種,做任務也是一種

public void upgrade() {

System.out.println(this.name + "又升了一級!");

}

}

// 普通代理的代理者

public class GamePlayerProxy implements IGamePlayer {

private IGamePlayer gamePlayer = null;

// 通過建構函式傳遞要對誰進行代練

public GamePlayerProxy(String name) {

try{

gamePlayer = new GamePlayer(this.name);

} catch (Exception e) {

// TDO 異常處理

}

}


// 打怪,最期望的就是殺老怪

public void killBoss() {

this.gamePlayer.killBoss();

}

// 進遊戲之前你肯定要登入吧,這是一個必要條件

public void login(String user, String password) {

this.gamePlayer.login(user, password);

}

// 升級,升級有很多方法,花錢買也是一種,做任務也是一種

public void upgrade() {

this.gamePlayer.upgrade();

}

}

// 普通代理的場景類

public class Client {

public static void main(String[] args) {

// 然後再定義一個代練者

IGamePlayer proxy = new GamePlayerProxy("張三");

// 開始打遊戲,記下時間戳

System.out.println("開始時間是:2017-01-01 23:27");

proxy.login("zhangSan","password");

// 開始殺怪

proxy.killBoss();

// 升級

proxy.upgrade();

// 記錄結束遊戲時間

System.out.println("結束時間是:2017-01-02 01:30");


}

}

// 強制代理的介面類

public interface IGamePlayer {

// 登入遊戲

public void login(String user , String password);

// 殺怪,這是網路遊戲的 主要特色

public void killBoss();

//升級

public void upgrade();

// 每個人都可以找一下自己的代理

public IGamePlayer getProxy();

}

// 強制代理的真實角色

public class GamePlayer Implements IGamePlayer {

private String name = "";

// 我的代理是誰

private IGamePlayer proxy = null;

public GamePlayer(String _name) {

this.name = _name;

}

// 找到自己的代理

public IGamePlayer getProxy() {

this.proxy = new GamePlayerProxy(this);

return this.proxy;

}

// 打怪,最期望的是殺老怪

public void killBoss() {

if(this.isProxy()) {

System.out.println(this.name + "在打怪!");

} else {

System.out.println("請使用指定的代理訪問");

}

}

// 進遊戲之前你肯定要登入遊戲吧,這是一個必要條件

public void login(String user , String password) {

if(this.isProxy()) {

System.out.println("登陸名為" + user + "的使用者" + this.name + "登入成功!");

} else {

System.out.println("請使用指定的代理訪問");

}

}

// 升級,升級有很多方法,花錢買是一種,做任務也是一種

public void upgrade(){

if(this.isProxy()) {

System.out.println(this.name + " 又升了一級!");

} else {

System.out.println("請使用指定的代理訪問");

}

}

// 校驗是否是代理訪問

private boolean isProxy() {

if(this.proxy == null) {

return false;

} else {

return true;

}

}

}


// 強制代理的代理者

public class GamePlayerProxy implements IGamePlayer {

private IGamePlayer gamePlayer = null;

// 通過建構函式傳遞要對誰進行代練

public GamePlayerProxy(IGamePlayer _gamePlayer) {

this.gamePlayer = _gamePlayer;

}


// 打怪,最期望的就是殺老怪

public void killBoss() {

this.gamePlayer.killBoss();

}

// 進遊戲之前你肯定要登入吧,這是一個必要條件

public void login(String user, String password) {

this.gamePlayer.login(user, password);

}

// 升級,升級有很多方法,花錢買也是一種,做任務也是一種

public void upgrade() {

this.gamePlayer.upgrade();

}

// 代理的代理暫時還沒有,就是自己

public IgamePlayer getProxy() {

return this;

}


}

// 強制代理的場景類

public class Client {

public static void main(String[] args) {

// 定義一個遊戲的角色

IGamePlayer player = new GamePlayer("張三");

// 獲得指定的代理

IGamePlayer proxy = player.getProxy();

// 開始打遊戲,記下時間戳

System.out.println("開始時間是:2017-01-01 23:27");

proxy.login("zhangSan","password");

// 開始殺怪

proxy.killBoss();

// 升級

proxy.upgrade();

// 記錄結束遊戲時間

System.out.println("結束時間是:2017-01-02 01:30");


}

}

// 代理是有個性的

代理類的介面

public interface IProxy {

// 計算費用

public void count();

}

// 代理類


public class GamePlayerProxy implements IGamePlayer, IProxy {

private IGamePlayer gamePlayer = null;

// 通過建構函式傳遞要對誰進行代練

public GamePlayerProxy(IGamePlayer _gamePlayer) {

this.gamePlayer = _gamePlayer;

}

// 代練殺怪

public void killBoss() {

this.gamePlayer.killBoss();

}

// 代練登入

public void login(String user, String password) {

this.gamePlayer.login(user, password);

}

// 代練升級

public void upgrade() {

this.gamePlayer.upgrade();

this.count();

} 

// 計算費用

public void count() {

System.out.println("升級總費用是:150元");

}

}