<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
    數(shù)據(jù)加載中……

    【設(shè)計模式】有關(guān)策略模式

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

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

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

            場景:構(gòu)建一個電子商務(wù)系統(tǒng),要處理不同地區(qū)的業(yè)務(wù),地區(qū)不同業(yè)務(wù)處理規(guī)則可能有點區(qū)別。

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

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

            如何實例化和管理這些策略?誰承擔(dān)這個責(zé)任?
            假設(shè),有了兩個實現(xiàn),分別針對A區(qū)域和B區(qū)域:   
    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 }
            
            假設(shè),現(xiàn)在客戶端如下使用:
     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         //
               客戶端首先獲取對應(yīng)的region信息,然后if else去創(chuàng)建對應(yīng)的策略實例,然后再去調(diào)用這些實例上的服務(wù).......那如果有個中間角色來管理這些策略,是不是能夠把類型的使用和類型的實例化分開呢?引入一個管理器角色看一下:
    1 public class PolicyManager {
    2     private PolicyManager() {}
    3     
    4     public static PolicyManager getInstance() {//}
    5     
    6     public IPolicy getPolicy(String region) {//}
    7 
    8 }
            
            客戶端調(diào)用代碼變?yōu)槿缦拢?br />
    1        //
    2         String region = requst.getRegion();
    3         IPolicy policy = PolicyManager.getInstance().getPolicy(region);
    4         boolean result = policy.process(request);
    5         //
            比較前面的調(diào)用代碼,我們發(fā)現(xiàn),客戶端少干了一件事情:實例化和管理實例!!!  而且這樣也可以做到具體的Policy實現(xiàn)類型對客戶端隱藏,客戶端真正基于接口。上面的PolicyManager我并沒有具體寫如何管理實例,在本問題場景下,只要保證一點就可以了,用戶找你這個manager去獲取指定region的策略。~_~

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

            控制上下文如何設(shè)計...?
            你的策略如何面對異常情況?例如發(fā)生異常時怎么辦?異常信息又如何處理?是否可以把異常信息都收集起來呢,這樣可以針對這些異常信息做各種處理  等等
            例如,可能將接口調(diào)整如下:
            
    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         //

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


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

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

    本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請注明出處,謝謝!

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

    評論

    # re: 【設(shè)計模式】有關(guān)策略模式  回復(fù)  更多評論   

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

    # re: 【設(shè)計模式】有關(guān)策略模式  回復(fù)  更多評論   

    > 數(shù)據(jù)上下文合理嗎?

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

    # re: 【設(shè)計模式】有關(guān)策略模式  回復(fù)  更多評論   

    @linuxer
    你說的是一種辦法,在很多場景下可以這么做。我寫這篇隨筆的時候,就想集中精力來看一下一個行為封裝伴隨的上下文問題...
    2008-09-04 10:03 | zhuxing
    主站蜘蛛池模板: 亚洲AV成人无码网天堂| 亚洲成AV人片在线观看| 亚洲春黄在线观看| 91成人在线免费视频| 亚洲v高清理论电影| 丁香花在线视频观看免费| 亚洲一区二区三区AV无码| 人妻在线日韩免费视频| 久久精品国产96精品亚洲| 国产精品免费看久久久 | 97性无码区免费| 久久精品国产亚洲AV久| 免费精品人在线二线三线区别| 中日韩亚洲人成无码网站| 男女啪啪永久免费观看网站| 人妻无码中文字幕免费视频蜜桃| ZZIJZZIJ亚洲日本少妇JIZJIZ| 成人自慰女黄网站免费大全| 久久精品国产精品亚洲精品| 亚洲成年人免费网站| 亚洲精品无码成人片久久不卡 | 成人毛片免费视频| 污网站在线观看免费| 精品国产亚洲一区二区三区| 亚洲精品视频免费看| 亚洲国产精品综合久久20| 免费国产成人高清在线观看麻豆 | 精品久久免费视频| 一级特黄色毛片免费看| 亚洲国产成人片在线观看无码| 麻豆一区二区免费播放网站| 久久精品国产亚洲AV电影网| 久久亚洲精品视频| 免费阿v网站在线观看g| 色吊丝免费观看网站| 亚洲一区精品中文字幕| 国产麻豆剧传媒精品国产免费| 成人爽a毛片免费| 亚洲午夜精品久久久久久app| 国产成人亚洲综合无码| 国产92成人精品视频免费|