關於代理模式,咱們聽到的見到的最多的可能就是靜態代理、動態代理之類的,固然還有你們都知道的Spring Aop,這裏咱們先不談這些個代理,先說個簡單的例子。遊戲代練應該都據說過,許多人確定也找過代練,曾經DNF、LOL、COC等等遊戲的代練不少,固然如今各種遊戲層出不窮,也都有各類代練,那這裏所謂的代練是什麼?就是Proxy,也即代理類,那遊戲代練這件事就是一個代理模式。html
若是以爲很差理解能夠這麼想,代練的流程是,你把本身的帳號交給代練人員,讓他們幫你打怪升級,而你只須要提供帳號便可。那代練人員那邊,他所要作的就是登錄你的帳號,而後替你打遊戲,從第三者的角度來看,你這個角色在打怪升級,但這個第三者並不知道是否是你本人在打遊戲,他只能看到你這個帳號正在打怪升級,但並不須要知道後面打遊戲的是誰。這就是代理模式,由他人代理玩遊戲。git
若是以爲這個還很差理解,那再說一個例子。假設我如今要邀請明星來上節目,我是直接給這個明星打電話嗎?固然不是,是給他的經紀人打電話,而後再由經紀人通知到該明星,這裏經紀人充當的就是代理的角色。設計模式
更常見的例子就是Windows的快捷方式,經過快捷方式,咱們能夠訪問某個文件夾下的exe文件,這就是一個典型的代理模式,它將接口,按上面遊戲的說法說就是代練的帳號,提供了出來,咱們只需點擊快捷方式,它會幫咱們運行指定目錄下的指定程序。說了這麼多,如今來看一下代理模式的定義。安全
代理模式(Proxy),爲其餘對象提供一種代理以控制對這個對象的訪問。UML結構圖以下:ide
其中,Subject是主題角色,定義了RealSubject和Proxy的共同接口;RealSubject是具體主題角色,定義了Proxy所表明的真實實體;Proxy爲代理主題角色,保存一個引用使代理能夠訪問實體,並提供一個與Subject的接口相同的接口。this
定義了RealSubject和Proxy的共同接口,這樣就在任何使用RealSubject的地方均可以使用Proxy。spa
1 public abstract class Subject { 2 3 public abstract void request(); 4 5 }
定義了Proxy所表明的真實實體。設計
1 public class RealSubject extends Subject { 2 3 @Override 4 public void request() { 5 System.out.println("真實的請求RealSubject"); 6 } 7 8 }
代理類。一個代理類能夠代理多個被委託者或被代理者,所以一個代理類具體代理哪一個真實主題角色,是由場景類決定的。代理
1 public class Proxy extends Subject { 2 3 private RealSubject realSubject = null; 4 5 public Proxy() { 6 this.realSubject = new RealSubject(); 7 } 8 9 @Override 10 public void request() { 11 this.before(); 12 this.realSubject.request(); 13 this.after(); 14 } 15 16 //預處理 17 private void before() { 18 System.out.println("-------before------"); 19 } 20 21 //善後處理 22 private void after() { 23 System.out.println("-------after-------"); 24 } 25 }
1 public class Client { 2 3 public static void main(String[] args) { 4 Proxy proxy = new Proxy(); 5 proxy.request(); 6 } 7 8 }
運行結果以下:code
這個結果和Spring的AOP很相似,能夠相互對照一下。
這裏咱們就以上面說過的遊戲代練爲例。UML圖以下:
遊戲玩家接口。由登錄、殺怪、升級三個方法。
1 public interface IGamePlayer { 2 //登錄 3 public void login(String user, String password); 4 //殺怪 5 public void killBoss(); 6 //升級 7 public void upgrade(); 8 }
遊戲玩家。正常玩家登錄、打怪、升級。
1 public class GamePlayer implements IGamePlayer { 2 3 private String name = ""; 4 5 public GamePlayer(String name) { 6 this.name = name; 7 } 8 9 @Override 10 public void login(String user, String password) { 11 System.out.println("登陸名爲<" + user + ">的用戶<" + this.name + ">登錄成功!"); 12 } 13 14 @Override 15 public void killBoss() { 16 System.out.println("<" + this.name + ">在打怪!"); 17 } 18 19 @Override 20 public void upgrade() { 21 System.out.println("<" + this.name + ">升了一級!"); 22 } 23 24 }
遊戲代練。也即代理類,用於代替玩家登錄、打怪、升級。
1 public class GamePlayerProxy implements IGamePlayer { 2 3 private IGamePlayer gamePlayer = null; 4 5 public GamePlayerProxy(IGamePlayer gamePlayer) { 6 this.gamePlayer = gamePlayer; 7 } 8 9 @Override 10 public void login(String user, String password) { 11 this.gamePlayer.login(user, password); 12 } 13 14 @Override 15 public void killBoss() { 16 this.gamePlayer.killBoss(); 17 } 18 19 @Override 20 public void upgrade() { 21 this.gamePlayer.upgrade(); 22 } 23 24 }
玩家找了一個代練,代練登錄了該玩家的帳號,而後替該玩家打怪升級。
1 public class Client { 2 3 public static void main(String[] args) { 4 //定義一個玩家 5 IGamePlayer player = new GamePlayer("桐人"); 6 //定義一個代練 7 IGamePlayer proxy = new GamePlayerProxy(player); 8 9 //開始打遊戲 10 //登錄 11 proxy.login("adam", "123456"); 12 //開始殺怪 13 proxy.killBoss(); 14 //升級 15 proxy.upgrade(); 16 } 17 18 }
運行結果以下:
從這個結果咱們只能看到有人登錄了這個帳號,他正在打怪升級,但並不知道是否是代練,這就是代理模式。
有關代理模式的延伸(靜態代理、動態代理)詳見《簡說設計模式——代理模式(續)》。