一:為什麼學習代理模式:
代理模式實際上是SpringAOP的底層! 【SpringAOP 和 SpringMVC (面試必問)】
二:代理模式(基本概念):
基本概念:代理模式的核心作用就是通過代理,控制對物件的訪問。這跟實際中是一樣的,例如說我們租房子時遇到的中介,這就是一個代理,比如有人要找中介幫忙出租房屋,那麼首先處理這事的就是中介,雖然自己的房子需要出租給其他人,但是出租房子前後的一些必須要做的事(帶住客看房,簽訂住房合同,收取租房費用)等等,都由這個中介來處理。
在程式中也是如此,為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個物件不適合或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。這也是AOP的實現原理。
三:那麼代理模式的核心角色該如何設計呢?
角色分析:
·抽象角色: 通過介面或抽象類宣告真實角色實現的業務方法
·真實角色: 實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色呼叫。(被代理的角色)它只關注真正的業務邏輯,比如拍戲。
·代理角色: 實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。如談合同,佈置場地等等。
·客戶:訪問代理物件的人
四:代理模式的分類
1、靜態代理 (靜態代理是我們自己建立一個代理類) 【本篇文章我們先深入瞭解靜態代理模式,動態代理下篇文章給大家講解】
2、動態代理 (動態代理是程式自動幫我們生成一個代理)
五:靜態代理(來個程式碼看看吧)
1、根據上面的實現步驟,首先來寫一個抽象角色
1 //租房的介面 (抽象角色) 2 3 public interface Rent { 4 5 void rent(); 6 7 }
2、寫一個真實角色(實現抽象角色類)
1 //房東 要出租房子 (真實的角色) 2 3 public class Host implements Rent { 4 @Override 5 public void rent() { 6 System.out.println("房東要出租房子"); 7 } 8 }
3、寫一個代理角色(實現抽象角色類)
1 // 中介 幫助房東出租房子 (代理角色) 2 3 public class Proxy implements Rent { 4 5 //使用組合 (也可以使用繼承,但java為單根繼承,故有限制性,所以在這裡我們使用組合的方式) 6 private Host host; 7 8 public Proxy() { 9 } 10 11 public Proxy(Host host) { 12 this.host = host; 13 } 14 15 //代理房東出租房屋 16 @Override 17 public void rent() { 18 seeHouse(); 19 host.rent(); 20 heTong(); 21 fare(); 22 } 23 24 //看房 25 public void seeHouse(){ 26 System.out.println("中介帶你看房!"); 27 } 28 //籤合同 29 public void heTong(){ 30 System.out.println("籤租賃合同!"); 31 } 32 //收中介費 33 public void fare(){ 34 System.out.println("收中介費!"); 35 } 36 37 }
4、寫一個客戶 (訪問代理角色的人,即需要租房子的人)
1 // 客戶 (需要租房子的人) 2 3 public class Client { 4 public static void main(String[] args) { 5 //原始方法,在找得到房東的情況下使用, 此處學習代理模式(故需建立一個代理角色) 6 // Host host=new Host(); 7 // host.rent(); 8 9 10 11 //代理模式 12 13 //房東要出租房子 14 Host host = new Host(); 15 //代理, 中介幫助房東出租房子,但是呢?代理角色一般會有一些附屬操作(看房,籤合同,收中介費等等)! 16 Proxy proxy = new Proxy(host); 17 //你不用面對房東,直接找中介租房子即可 18 proxy.rent(); 19 } 20 }
5、輸出結果為:
由輸出結果,可以看出,客戶只跟代理角色(中介)打交道,代理角色就會幫真實角色(房東)需要做的事情都做了(以及一些附屬操作)
六:代理模式的好處:
1、可以使真實角色的操作更加純粹!就是實現實際的業務邏輯,不用關心其他非本職責的事務,通過後期的代理完成一切事務,附帶的結果就是程式設計簡潔清晰。
2、公共業務就交給代理角色!實現了業務的分工!代理角色可以在客戶端和目標物件之間起到中介的作用,這樣起到了中介的作用和保護了目標物件的作用。
3、公共業務發生擴充套件的時候,方便集中管理 (高擴充套件性)
缺點:
1、一個真實角色就會產生一個代理角色;程式碼量會翻倍---開發效率會變低
七:針對代理模式的高擴充套件性進行(加深理解)
(程式碼示例)在不改變原有業務的情況下,擴充套件一些功能 (本示例為: 擴充套件日誌功能)
1、抽象角色
1 //抽象角色 2 public interface UserService { 3 4 void add(); 5 void delete(); 6 void update(); 7 void query(); 8 }
2、真實角色
1 //真實角色 2 3 public class UserServiceImpl implements UserService { 4 @Override 5 public void add() { 6 System.out.println("增加了一個使用者"); 7 } 8 9 @Override 10 public void delete() { 11 System.out.println("刪除了一個使用者"); 12 } 13 14 @Override 15 public void update() { 16 System.out.println("修改了一個使用者"); 17 } 18 19 @Override 20 public void query() { 21 System.out.println("查詢了一個使用者"); 22 } 23 24 }
3、代理角色
1 //在不改變原有業務的情況下,擴充套件一些功能 (本示例為: 擴充套件日誌功能) 2 3 public class UserServiceProxy implements UserService { 4 5 private UserServiceImpl userService; 6 7 //Spring 中不建議使用 有參構造組合 8 // public UserServiceProxy(UserServiceImpl userService) { 9 // this.userService = userService; 10 // } 11 12 //Spring 中注入一個物件,建議使用set方法 13 public void setUserService(UserServiceImpl userService) { 14 this.userService = userService; 15 } 16 17 @Override 18 public void add() { 19 log("add"); 20 userService.add(); 21 } 22 23 @Override 24 public void delete() { 25 log("delete"); 26 userService.delete(); 27 } 28 29 @Override 30 public void update() { 31 log("update"); 32 userService.update(); 33 } 34 35 @Override 36 public void query() { 37 log("query"); 38 userService.query(); 39 } 40 41 //日誌方法 42 public void log(String msg){ 43 System.out.println("[Debug] 使用了"+msg+"方法"); 44 } 45 }
4、客戶 (測試類)
1 //測試類 2 3 public class Client { 4 public static void main(String[] args) { 5 //真實角色 6 UserServiceImpl userService=new UserServiceImpl(); 7 //代理角色 8 UserServiceProxy proxy=new UserServiceProxy(); 9 //代理真實角色 userService 10 proxy.setUserService(userService); 11 //代理實現查詢方法 12 proxy.query(); 13 } 14 }
5、輸出結果:
注: 大家針對 AOP 做一定深度的瞭解,瞭解代理模式底層,以及對 SpringAOP 和 SpringMVC 的使用 (面試高頻問)
下篇文章我們繼續解讀 【動態代理模式】