心得:Spring AOP和Decorator模式

xuesenlin發表於2004-10-27
最近這個段時間都是忙於學習 SpringFramework,那東東好樣的,只是剛剛學完Struts,Hibernate,有來了這個,呵呵,,感覺挺累的。
“你怎麼把這兩個不相干的東西撤到一起?” ,確實是這樣! 無論從他們的設計,
實現,使用等方面他們是風馬牛不相及, 但本人認為從理解的方面看他們有點類似。況且學習要從對比中學呀!這對初學者會有幫助於理解。
重要宣告:本人都是用自己的語言寫的,有專業術語不對還請大家指出。: - )
就說設計模式 Decorator,也就是裝飾模式,這還不好理解? 在原有的東西上進行裝飾一下便是裝飾了。既然是裝飾,你要有主體呀(被修飾的東西),還要有裝飾品。但是不管你裝飾來裝飾去,他的本質是不變的。 就象人帶上了面具,但他還是人。牆上打上了油漆,但它還是牆呀。你也許覺得這是廢話。 但理解這點很重要(這是跟策略模式Strategy的區別),本人覺得這個是理解好 Decorator 模式很重要的一點。在開發中你經常要增強一個類的功能,或者是撤銷一個類的某些功能,但是一個類給眾多的功能進行裝飾了以後,也許原來的類已經面目全非了,你往往會感到茫然,其實,你主要抓住他的主體,腦子裡面時刻要知道你現在所作的工作就是為這個主體進行打扮的工作。
研究過Jive的都知道, 裡面的 Filter 就是用了Decorator 設計模式,那麼在這個設計裡面,它的主體是什麼? ForumMessage ,無疑是 ForumMessage 。裝飾品當然是Filter 了,所以我們在作這件事情的時候始終是以ForumMessage為核心的,Filter 進行裝飾的時候,你千萬不要忘記你現在是為ForumMessage而工作!有關於jive研究的文章,網上一大堆,現在看看一個比較簡單的 Decorator:


//比如有一個抽象構件:
public interface Component {
   void operation();
}
//一個具體構件:
public class ConcreteComponent implements Component {
   public void operation() {
	//Write your code here
   }
}
//一個抽象裝飾:
public class Decorator implements Component {
   private Component component;  //引用
   … …. …. …
   //商業方法,委派給構件
   public void operation() {
      component.operation();
   }
}
//一個具體裝飾:
public class ConcreteDecorator extends Decorator {
   /**
     * 商業方法
     */
   public void operation(){
     //一些具體的裝飾的程式碼
     ......
      super.operation(); // 主體
     //一些具體的裝飾的程式碼
    .......
   }
}
<p class="indent">

......
我們主要看看,在ConcreteDecorator 中的operation() 方法,他的父類是委託到component組建來完成的,其實它就是主體, 一些裝飾程式碼都會在這個方法(主體)執行前進行“預處理”或是執行後進行“收尾”。
可不是,從上面很容易就看出了,抽象裝飾中的operation() 方法沒有在具體的裝飾類中進行“全盤”覆蓋,因為他用了super.operation(); 這樣的語句。可見裝飾模式中不管怎麼樣, 你都要找到類似這個的方法。說明他的主體還在。(這是跟策略模式Strategy的區別)
說了怎麼多,不知道大家有沒有感覺到ConcreteDecorator類中的operation()方法跟Spring AOP 中的 InvocationHandler 介面的invoke()方法有點相類是呢?
我們來看看要實現 InvocationHandler 時候要重寫的invoke()方法:


public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
   …………………….
   result = method.invoke(originalObject, args);
   ……………………………..
  return result;
}
<p class="indent">


InvocationHandler.invoke 方法將在被代理類的方法被呼叫之前觸發。透過這個方法中,我們可以在被代理類方法呼叫的前後進行一些處理,如上面程式碼中所示,InvocationHandler.invoke方法的引數中傳遞了當前被呼叫的方法(Method),以及被呼叫方法的引數。同時,我們可以透過Method.invoke方法呼叫被代理類的原始方法實現。這樣,我們就可以在被代理類的方法呼叫前後大做文章。(說明:引用了Spring 開發指南中的一段)
在回到裝飾模式,其方法operation() 在執行前和執行後,也可以對它大做文章。如此看來, Spring AOP 和 Decorator,從理解層面上來看,確實有點相象,注意:只是理解層面, 而他們的實現完全兩馬事!
其實主要是大家怎麼看待這個問題,按照本人的理解,Spring AOP 也可以說是一種廣義的裝飾,但它又不是裝飾模式。它同樣也是對某個方法加上了限制,比如insert() 的時候,你要對它做執行前開啟事務和執行後提交或回滾這樣的“裝飾”。 又比如你也可以對某個人操作資源後做log這樣的裝飾工作。等等,,
他們的相同之處就這麼點。
AOP 也不是什麼新的東西,當然如果你的AOP是容器(Jboss 4.0)實現的話, 那麼按照上面說的,你的一些方法就會被容器所“裝飾”。
如此看來,更多的時候可以理解為 Spring AOP 和一些AOP 容器是在系統級的,容器級的“裝飾”。 而裝飾模式則是業務級的裝飾。 這點其實從客戶端也很容易理解。
如果是AOP ,程式設計師可以放心的寫你的程式碼(即使有點笨也不怕,有AOP護著呢)。 因為系統將在系統執行時候對這段程式碼進行“裝飾”。也就是說,這些裝飾不會出現在客戶端的程式碼中,,,而,Decorator模式呢?呵呵,這個時候程式設計師要有點頭腦了,他們要自己組裝一些裝飾類,按照某一種機制對主體進行裝飾。也就是說,這些修飾類要出現在客戶端的程式碼中。看程式碼就知道了 :--)

InputStreamReader  input = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(input);
....//主體是System.in
<p class="indent">

哦 , 夠經典的例子!

相關文章