設計模式--IOC(DI)與AOP思想涉及的模式


這幾天簡單瞭解學習了Spring框架,其中的IOC(DI)與AOP的特性自然是其精髓所在,正好也在學習設計模式,結合設計模式理解了一下


1.IOC(DI)依賴注入--State模式

          依賴注入是什麼?首先看一個例子,工程中業務層類(Business)需要調用底層打印類(RealWriter)來完成自己的功能,關係圖如下:



Business類的save方法中會調用RealWriter實例的saveToReal方法,即Business類的功能實現依賴RealWriter類,可如果如今我們又多了一種Writer的實現方式,區別於原來的RealWriter類的功能,此時因爲Business直接依賴於RealWriter類,我們無法直接使用既有的Business類了,只能大動干戈地修改Business類,這種情況下,IOC(DI)的思想的優勢就體現出來了—“程序不應依賴實現,而是依賴於抽象接口”,於是我們把原來的依賴關係修改一下,如下圖:




首先我們定義了一個接口Writer並聲明瞭方法saveToWriter,使原先的RealWriter類和新增的OtherWriter類實現這個接口,將原來Business類中定義的具體類實例RealWriter改成接口Writer的聲明,並提供Writer的set方法(set方式注入依賴),在save方法邏輯裏直接調用接口的saveToWriter方法,這樣我們在使用Business的時候就可以通過注入(set方法)不同的實現類RealWriter,OtherWriter來實現自己的功能。這即是IOC的基本概念所在:通過抽象出對象的接口來實現依賴關係的反轉,即將控制權從實際的RealWriter類轉移至抽象的Writer接口。當然,Spring是通過配置文件來實現依賴注入的引入的,具體這裏就不說明了。


IOC的這種實現方式恰好就是狀態(State)模式的完整體現,我們例子中得RealWriter和OtherWriter就是兩種不同的狀態,利用抽象接口實現不同的狀態間的相互切換,便於功能擴展和耦合度的減輕。

具體參考代碼如下:

Writer.java

  1. <span style="font-size:18px;">public interface Writer {  
  2.     abstract void saveToWriter();  
  3. }</span>  


RealWriter.java

  1. <span style="font-size:18px;">public class RealWriter implements Writer {  
  2.     public void saveToWriter() {  
  3.         System.out.println("From the RealWriter");  
  4.     }  
  5. }</span>  

OtherWriter.java
  1. <span style="font-size:18px;">public class OtherWriter implements Writer {  
  2.     public void saveToWriter() {  
  3.         System.out.println("From the OtherWriter");  
  4.     }  
  5. }</span>  

Business.java
  1. <span style="font-size:18px;">public class Business {  
  2.     private Writer writer;  
  3.       
  4.     public void setWriter(Writer writer) {  
  5.         this.writer = writer;   
  6.     }  
  7.       
  8.     public void save() {  
  9.         System.out.println("Business--save:begin");  
  10.         writer.saveToWriter();  
  11.         System.out.println("Business--save:end");  
  12.     }  
  13. }</span>  


2.AOP面向切面--Proxy模式

度娘給的解釋是,AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程(也叫面向方面),可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術,我們可以理解爲在一個服務的流程中,插入與該服務的業務邏輯無關的系統服務邏輯,如日誌、安全認證等等。

 

例如我們需要在某個已經完成了的類的邏輯出來前後加上log的操作,直接在這個類裏面的邏輯裏修改是一種方式,卻也非常不好,因爲加入的東西與邏輯並無關係,而且若有大量的邏輯類需要增加,修改的量很大且容易出錯。Spring裏通過定義攔截器(interceptor)來實現AOP的功能,定義自己想要的行爲插入到預定插入的位置中,這種interceptor的攔截實現大概原理就是Proxy工廠類生產出對象代理,它包含了原對象的處理,插入欲進行的操作並返回,典型的代理(Proxy)模式,用一個關係圖來說明一下:


就是在代理類裏使用被代理對象的實例,功能方法裏調用此實例的方法,並在調用前後添加自己需要的操作,完整滿足被代理對象的功能之外完成其他服務的添加。

 

示例代碼如下:

Subject.java
  1. <span style="font-size:18px;">abstract public class Subject {  
  2.     abstract public void request();  
  3. }</span>  

RealSubject.java
  1. <span style="font-size:18px;">public class RealSubject extends Subject {  
  2.   
  3.     public RealSubject() {}  
  4.       
  5.     public void request() {  
  6.         System.out.println("From real subject.");         
  7.     }  
  8. }</span>  

RealSubject.java

  1. <span style="font-size:18px;">public class ProxySubject extends Subject {  
  2.   
  3.     private RealSubject realSubject;  
  4.       
  5.     public ProxySubject() {}  
  6.       
  7.     public void request() {  
  8.         preRequest();  
  9.           
  10.         if (realSubject == null) {  
  11.             realSubject = new RealSubject();  
  12.         }  
  13.         realSubject.request();  
  14.           
  15.         postRequest();  
  16.     }  
  17.       
  18.     private void preRequest() {  
  19.         System.out.println("do preRequest.");  
  20.     }  
  21.   
  22.     private void postRequest() {  
  23.         System.out.println("do postRequest.");  
  24.     }  
  25. }</span>  

用法爲:
  1. <span style="font-size:18px;">  Subject proxySubject = new ProxySubject();  
  2.     proxySubject.request();</span>  

對於IOC、AOP及狀態模式、代理模式還是剛剛瞭解一下,還需要繼續學習,學習學習.....
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章