Struts2中的設計模式


http://blog.csdn.net/significantfrank/article/details/7712053

1. Command Pattern

基本定義: 把Command(Request)封裝成對象,把發出命令(Invoker)的責任和執行命令(Receiver)的責任分割開,委派給不同的對象。

責任划分有什么好處?

責任約單一,內聚性越高,可重用的可能性越大,試想下,如果服務員不僅要點菜,還要去做菜,會是什么情景。

為什么把Invoker和Receiver解耦好處多?

 

類之間的耦合越低,可擴展的可能性越高。解耦后,更換一個服務員並不會影響廚師的工作

 

那么把Request封裝成對象具體是什么意思呢?

在遙控器Remote Control例子中,比如我有一個‘開燈’的Request,那么就應該對應有一個LightOnCommand對象,關燈就應該有LightOffCommand

在Web應用中,我有一個add user的Request,那么就應有一個AddUserCommand去處理請求, 或者用struts的name convention就是AddUserAction.

那么在Struts中又是怎么運用Command Pattern的呢?

Client : FilterDispatcher Servlet

Invoker: ActionInvocation

Command: Action (not a must in Struts2)

ConcreteCommandAddUserAction

Receiver: ServiceImpl (not a must, depends how many logic you want to put into concreteCommand)

Struts,你什么時候調用的setCommand()?

用戶定義了Action Mapping在struts.xml里,在web container啟動時,ConfigurationManager 就裝載了struts.xml,當Request過來時,Struts Framework會根據當前的URL去找ConfigurationManager所對應的concreteCommand/Action,  然后這個Action會被set到ActionInvocation

Command Interface是必須的嗎?

在struts1中,有一個Interface,所有的Action都必須是它的實現。但是在Struts2中,Action可以是任意的POJO,因為在Runtime的時候,具體的Action是什么,該調用它的什么方法,都可以通過配置文件(MetaData)+ Java Reflection來實現。這種新方式的好處是POJO Action沒有了對框架的依賴,測試將會更加容易。缺點是因為沒有interface的約束,調用Action的什么方法完全取決於默認值(比如execute)或是配置文件中的配置。若設置不妥,只有在Runtime的時候才能發現錯誤。

Receiver 是必須得嗎?

不是,取決於你Action的厚度,如果你想讓Action很輕的話,那么通常你會在Action中使用UserService.addUser()去做事情,此時的UserService就是Receiver。把Action設計的厚點,直接把addUser的logic放在Action中也是可以的。

Struts2中運用了command的思想,但並沒有嚴格的按照其經典模型實現,而是做了些變通,這些變通乍看起來可能是有點違背設計原則,比如說取消了Action Interface,這不是反模式嗎,反面向接口的編程嗎,但仔細想想,這里我們真的需要這個接口嗎?通過配置文件+Reflection,我們同樣可以做到在Runtime的時候給ActionInvocation注入不同的Action的目的。而接口卻增加了用戶實現對框架的依賴,降低了程序的可測性,所以這樣的變通其實是有積極意義的,雖然我們損失了一點點接口作為契約所帶來的好處。

2. Interceptor Pattern

於其說這是模式,不如說這是AOP和Pipeline思想的結合,只不過Struts2中的實現非常的精巧,我不得不說這應該作為一個模式來推廣。

AOP : 所謂的AOP就是preProcess and postProcess, 系統應用中,許多地方是需要面向切面的,比如log,authentication,etc...。看過一些實現,如Java Dynamic,但不夠優雅。

Pipeline:分層就是把復雜的問題分層多個層次,每一層只處理問題的一小部分。通信的7層模型就是典型的范例

Interceptor Pattern 不僅為系統進行分層,而且還提供了AOP的處理,此外,還以一種plug-in的方式為用戶提供了無限擴展的可能。

應該怎么實現?

Interceptor的調用過程類似於一個棧式調用,所以想到遞歸是很自然的,這既避免了像Dynamic Proxy那樣的hack,又提供了更好的擴展性。

 還是以Struts中的類作為例子,其類圖如下:

調用過程:

Pseudo 代碼:

ActionInvocation

 

  1. public Result invoke(){  
  2.     if( interceptors.hasNext() ){  
  3.         Interceptor interceptor = interceptors.next();  
  4.         result = interceptor.intercept(this);  
  5.     }  
  6.     else {  
  7.         action.execute();//如果沒有更多的Interceptor,停止遞歸,調用action  
  8.     }  
  9. }  
public Result invoke(){
    if( interceptors.hasNext() ){
        Interceptor interceptor = interceptors.next();
        result = interceptor.intercept(this);
    }
    else {
        action.execute();//如果沒有更多的Interceptor,停止遞歸,調用action
    }
}

InterceptorImpl

 

  1. public SomeInterceptor implements Interceptor{  
  2.     public Result intercept(ActionInvocation actionInvocation){       
  3.        //pre-processing  
  4.         
  5.         // 遞歸調用  
  6.         result = actionInvocation.invoke();  
  7.   
  8.        //post-processing  
  9.          
  10.        return result;  
  11.     }  
  12. }  
public SomeInterceptor implements Interceptor{
    public Result intercept(ActionInvocation actionInvocation){     
       //pre-processing
      
        // 遞歸調用
        result = actionInvocation.invoke();

       //post-processing
       
       return result;
    }
}

 

More: http://www.cnblogs.com/west-link/archive/2011/06/22/2086591.html

 

http://bosy.dailydev.org/2007/04/interceptor-design-pattern.html

Struts2 架構圖

Struts 2 framework: http://viralpatel.net/blogs/introduction-to-struts-2-framework/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM