<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Live a simple life

    沉默(zhu_xing@live.cn)
    隨筆 - 48, 文章 - 0, 評論 - 132, 引用 - 0
    數據加載中……

    【設計模式】有關策略模式

            對于工廠、策略、命令、適配、模版方法等模式大家應該都非常清楚了,因為這是使用極其頻繁的一些模式。如果對于設計模式不是很清楚,估計也應該是在無形中使用了。剛review一塊代碼,想起和策略模式使用的時候的幾個問題,僅供大家參考。
            說明:本人對設計模式理解很有限,工作經驗也不長,歡迎指正,謝絕諷刺、挖苦^_^

            【策略模式的本質】
               如果先來無事想一下經典的23個OO設計模式,部分其實就是在良好地利用繼承,部分則是避免繼承,當然是否使用繼承是由技術需求決定的。“繼承封裝變化”這句話聽的耳朵都起繭子了,繼承是多態的結構基礎,多態特性給予了針對不同實例對同一請求做出不同反應的能力。我們在遇到可變的點時候,一般處理如下:
            1、對可變點抽象出一個共性的概念,用繼承封裝這種變化
            2、在客戶端以引用的方式使用這種概念
            很顯然,上面1的結果是產生抽象類型(往往是對外暴露,基于接口),并繼承產生一系列擴展實現(往往是作為擴展實現,不一定對外暴露),上面2則需要我們思考如何構造實例,推薦的是講類型本身和類型實例的構造進行分離(是客戶端自己構造,還是有個工廠類型的角色來負責這種構造?如果有個工廠的角色來承擔實例化的任務,那么這些擴展實現則跟容易隱藏)。
            『PS:我們常說的基于接口編程,但是接口本身必然是不能實例化的,那么是用戶訪問具體實現類型構造函數來實例化呢,還是從一個工廠中去取呢? 當然,理論上后者更好,也是基于接口編程的重要保證手段!』
            我們的策略模式精髓是:將算法(特定類型行為邏輯)封裝進對象,便于獨立使用。廣義的講,處理上面說的變化的點的手段有很多種,策略模式是其中之一,設計模式是工具層面^_^ (需求中變化的點如何處理,策略模式可能用的上,絕對不是想用策略模式,去產生一些變化的點)。但是,使用策略模式的經驗告訴我們,定義的算法接口經常要修改...

            【策略模式使用時候的幾個疑問】
            先說幾個疑問:1、數據上下文合理嗎;2、策略本身是否需要實例狀態;3、如何實例化和管理這些策略;4、行為控制上下文如何處理

            場景:構建一個電子商務系統,要處理不同地區的業務,地區不同業務處理規則可能有點區別。

            很自然的,我們剛開始定義如下的接口(就叫做IPolicy吧 ~_~):
    1 public interface IPolicy {
    2     public boolean process(String id, String account);
    3 }
           上面的id、account等參數就是我們處理一個訂單需要的參數,也是從一個請求(Requst)數據結構中的部分信息。到這里,感覺一起OK。

            數據上下文合理呢?
            這個疑問出來,才回想起來,在定義IPolicy接口的時候,對process操作接受的數據上下文并沒有進行足夠的分析。可能就是假借一個地區的訂單處理想了一下,處理一個訂單需要這些信息。
            隨著新地區訂單策略實現的加入,最有可能帶來的一個問題就是:你的process給的參數信息不夠!!!一旦不夠,那么你要修改的就是接口定義了,這個時候可能已經有一些策略實現了,修改吧!!!
            對IPolicy接口修改如下:
    1 public interface IPolicy {
    2     public boolean process(Request request);
    3 }
            這里的Request是從系統接受到的請求(假設是從一個web service過來的,上面的id、account就是從Request中獲取來的),那么Request里面的信息一般來說對于處理一個請求是足夠的了, 這樣你定義的IPolicy就更能夠應對數據上下文的變化了。

            如何實例化和管理這些策略?誰承擔這個責任?
            假設,有了兩個實現,分別針對A區域和B區域:   
    1 public class RegionAPolicy implements IPolicy {
    2     
    3     public boolean process(Request request) {
    4         //
    5         return true;
    6     }
    7 }
            
    1 public class RegionBPolicy implements IPolicy {
    2     
    3     public boolean process(Request request) {
    4         //
    5         return true;
    6     }
    7 }
            
            假設,現在客戶端如下使用:
     1 //
     2         String region = requst.getRegion();
     3         if ("A".equalsIgnoreCase(region)) {
     4             IPolicy policy = new RegionAPolicy();
     5             boolean result = policy.process(request);
     6             //
     7         }
     8         else if ("B".equalsIgnoreCase(region)) {
     9             IPolicy policy = new RegionBPolicy();
    10             boolean result = policy.process(request);
    11             //
    12         }
    13         //
               客戶端首先獲取對應的region信息,然后if else去創建對應的策略實例,然后再去調用這些實例上的服務.......那如果有個中間角色來管理這些策略,是不是能夠把類型的使用和類型的實例化分開呢?引入一個管理器角色看一下:
    1 public class PolicyManager {
    2     private PolicyManager() {}
    3     
    4     public static PolicyManager getInstance() {//}
    5     
    6     public IPolicy getPolicy(String region) {//}
    7 
    8 }
            
            客戶端調用代碼變為如下:
    1        //
    2         String region = requst.getRegion();
    3         IPolicy policy = PolicyManager.getInstance().getPolicy(region);
    4         boolean result = policy.process(request);
    5         //
            比較前面的調用代碼,我們發現,客戶端少干了一件事情:實例化和管理實例!!!  而且這樣也可以做到具體的Policy實現類型對客戶端隱藏,客戶端真正基于接口。上面的PolicyManager我并沒有具體寫如何管理實例,在本問題場景下,只要保證一點就可以了,用戶找你這個manager去獲取指定region的策略。~_~

            策略對象需要實例狀態嗎?可以當作單態處理嗎?需要同步化嗎?
            需要分析你的策略,準確地判斷你的策略實例是否需要實例字段來表示狀態。一般是不需要的~_~ 如果引入實例變量,你的策略要有相應的管理...
           如果可以認為是單太的,那么同步化...

            控制上下文如何設計...?
            你的策略如何面對異常情況?例如發生異常時怎么辦?異常信息又如何處理?是否可以把異常信息都收集起來呢,這樣可以針對這些異常信息做各種處理  等等
            例如,可能將接口調整如下:
            
    1 public interface IMessageCollector {
    2     public void reportError();
    3     
    4     public void reportWarning();
    5 }

    1 public interface IPolicy {
    2     public boolean process(Object request, IMessageCollector collector);
    3 }
            
            
     1 //
     2         IMessageCollector messageCollector = new MessageCollectorImpl();
     3         
     4         String region = requst.getRegion();
     5         IPolicy policy = PolicyManager.getInstance().getPolicy(region);
     6         boolean result = policy.process(request, messageCollector);
     7         
     8         if (!result) {
     9             //TODO:處理messageCollector的一些錯誤和警告信息等
    10         }
    11         //

            這樣我們的異常信息的就可以集中管理,可以在客戶端做各種處理,而不需要修改策略本身,加強策略本身的復用。


            后記
            既然我們使用策略來封裝策略變化,那么我們應該也要思考如何讓我們的策略減少修改、易于擴展。其實如何將設計模式和一些基本的OO設計原則合理配合,在原則的指導下去用設計模式這個工具...是個很大的話題,不知道怎么去說。

            以上寫的是一點自己的感想,大家有什么好的意見,敬請分享一下。文中的示意代碼僅僅是為了輔助說明問題~_~

    本博客中的所有文章、隨筆除了標題中含有引用或者轉載字樣的,其他均為原創。轉載請注明出處,謝謝!

    posted on 2008-09-03 11:41 zhuxing 閱讀(1542) 評論(3)  編輯  收藏 所屬分類: Java設計

    評論

    # re: 【設計模式】有關策略模式  回復  更多評論   

    不錯,寫的有道理,非常贊同一些觀點!
    2008-09-03 13:14 | Jack.Wang

    # re: 【設計模式】有關策略模式  回復  更多評論   

    > 數據上下文合理嗎?

    結合采用command模式。
    2008-09-04 00:44 | linuxer

    # re: 【設計模式】有關策略模式  回復  更多評論   

    @linuxer
    你說的是一種辦法,在很多場景下可以這么做。我寫這篇隨筆的時候,就想集中精力來看一下一個行為封裝伴隨的上下文問題...
    2008-09-04 10:03 | zhuxing
    主站蜘蛛池模板: 永久在线毛片免费观看| 99999久久久久久亚洲| 日本大片在线看黄a∨免费 | 337P日本欧洲亚洲大胆艺术图| 日韩成人免费视频播放| 最近最新高清免费中文字幕| 亚洲免费在线视频播放| 亚洲A∨无码一区二区三区| 亚洲第一区精品观看| 日韩在线a视频免费播放| 18禁网站免费无遮挡无码中文 | 久久精品国产亚洲av天美18 | a毛片久久免费观看| 亚洲av成人一区二区三区| 亚洲成Av人片乱码色午夜| 亚洲一本大道无码av天堂| 国产成人无码区免费A∨视频网站 国产成人涩涩涩视频在线观看免费 | 亚洲av无码成人精品区在线播放| 日本免费中文字幕| 亚洲免费在线观看| 亚洲不卡1卡2卡三卡2021麻豆| 四虎影在线永久免费四虎地址8848aa| 国产99久久久国产精免费| 亚洲va精品中文字幕| 精品国产亚洲男女在线线电影| 99久9在线|免费| 国产成人久久AV免费| 久久这里只精品热免费99| 先锋影音资源片午夜在线观看视频免费播放 | 亚洲女子高潮不断爆白浆| 亚洲无码在线播放| 免费无码AV电影在线观看| 国产免费丝袜调教视频| 亚欧免费视频一区二区三区| 最好看最新的中文字幕免费| 120秒男女动态视频免费| 国产精品极品美女自在线观看免费| 亚洲一级片在线观看| 久久精品亚洲综合| 久久亚洲精精品中文字幕| 亚洲熟妇无码久久精品|