設計模式(一) 策略模式


    序言

       最近在看Head First 設計模式這本書,看了一點,第一感覺是簡單,通俗易懂,層序漸進,基本上稍微耐心一點都看得懂,那么這本書這么多優點,我寫博文是為了什么呢,方便自己以后觀看嗎?那我還不如看一遍書呢,既然書寫的那么好,寫給別人看?那還不如推薦別人直接去看書呢。寫着系列的博文這也沒用,那也沒用,那我的出發點是什么呢?  好。我腦袋中的構思是先講解一下每個模式的基本概念,也就是讓你們先知道講的這個模式的大概意思(盡量跟書上一樣簡單,就相當於我怎么想的告訴你們,你們可以用來借鑒,如果有更好的講解方式,可能一起討論),然后通過找一些實例,來看看這個模式在哪些地方用到了。加深我們的映像,讓我們學習設計模式的時候,也能學點別的東西。 這就是我寫這一系列博文的目的。 

                                                             --WZY

 

                 策略模式                   

 一、准備知識

         多態:父類對象引用子類實例對象,A extends B,A a = new B(); A、B中都有方法run,a.run();此時就是調用B中的run方法。這就是運行時多態,

            為什么叫運行時多態呢?因為在編譯的時候,不知道真正的a到底是什么,只知道a是A,在運行時才發現a是B的實例,調用的也就是B中的方法, 

            這樣做有什么好處?靈活性、簡化性、這種只能通過自己多敲代碼才能感覺得到使用多態的好處。。。

        行為組合:通過學習策略模式你就知道了什么是行為組合

 

二、什么是策略模式?

       在Head First設計模式的書中,用的鴨子的各種行為的例子來說明,看的我頭暈眼花,各種鴨子,橡皮鴨都出來了,而且是一步步帶領你進入到他所要說的那種思想上去。我感覺對於我這種不喜歡啰嗦麻煩的人來說,是個噩夢,直接看了下面這個圖,就理解了什么是策略模式

          一個游戲中有很多角色,有國王、王后、騎士、妖怪等人物,並且每個人物作戰的方式也不同,怎么實現呢?

      1、普通方法實現。

        看起來不錯啊,哈哈,應有盡有,但是缺點很多,

        1、如果king的戰斗方式需要改變呢,變成用槍了,那么我們只好在king類中增加一個GunBehavior方法,然后將fight中改為調用GunBehavior

        2、游戲不止三個騎士,那就來100個騎士,都使用弓箭,但是后面改革了,騎士改為用斧頭了,本來妖怪類中就已經實現了斧頭的方法,但沒辦法,我們還有自己在在騎士中實現一遍

        3、這樣一來,可擴展性和可復用性都非常差。每個人物中的方法都可能有重復。

       

 

      2、通過策略者模式怎么實現的呢?看下圖。

            1、變化的部分:每個人物使用的戰斗行為不一樣。所以將戰斗的行為都提取出來獨立當成一個類

            2、將戰斗行為抽取出一個接口來,為的就是使用接口編程的方式。

            3、在Character中申明一個WeaponBehavior變量,也就是為了接口編程后使用多態更方便。

              通過上面三步的改造,現在king使用什么戰斗方式,只需要new出來就行了,如果要使用槍,只需要在創建一個GunBehavior的類,然后讓king使用

              如果騎士,他們也想用斧頭,那么就把騎士中改一行代碼,改為用斧頭類就好了。

                        其實策略者模式最關鍵的就是將行為都提取出來封裝成獨立類,然后讓使用者想用什么就new什么。其他使用多態的地方只是設計原則所導致的。

 

      畫圖有點失誤,沒有將weapon.useWeapon()調用。sorry。

策略者模式用到了哪些設計原則?

    1、多用組合、少用繼承。這句話中的“組合”的意思就像上面的那些作戰行為都封裝成一個獨立的類,然后組合在一起。繼承在這個例子中並沒有體現出來。

    2、針對接口編程、而不是針對實現編程。 這個其實就是為了用多態。

    3、找出應用中可能需要變化的地方,把它們獨立出來,不要和那些不需要改變的代碼混在一起。

 

策略模式的標准結構圖

              

      

 

三、JDK中使用的策略模式體現

    1、Comparator接口

      記得那個Comparetor這個接口嗎,這個就是使用了策略模式寫的。在做Comparator和Comparable的比較的時候就說過,實現Comparator是在外部實現compareTo方法,而實現Comparable接口是在內部實現compareTo方法,現在知道為什么Comparator是在外部實現compareTo方法嗎,原因就是使用的是策略模式,每個功能/算法類,都必須實現策略接口。然后再需要使用該類的時候,在將其new出來使用.光說沒有用,帶你看一個非常熟悉的類。String類中就用到了

      首先看一下JDK中實現Comparator接口后擴展了一些什么類

          通過圖中可以看到實現該接口的類有很多,但是我們看到一個很熟悉的,java.lang.String下的一個類,說明這個CaseInsensitiveComparator在String中用到了。

    

          打開String的源碼,查看了一下,跟我們講解的一模一樣的形式

  

        

 

      不管這個類的作用是什么,反正我們是看到了熟悉的模式,

        1、CaseInsensitiveComparator實現了Comparator接口

        2、在String中Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();

            雖然這個是個常量,但是也沒什么大的差別,跟我們自己寫的規范是一樣的。

 

    2、ThreadPoolExecutor中的四種拒絕策略

        在JDK中,這個也使用了策略模式,有興趣的可以去看看,這里我就不帶着大家看了。

 

四、總結

      其實我們平常的代碼中,沒有那么復雜,只需要將其中變化的部分給抽取出來,達到復用的目的就行了,這種策略模式一般都是在那種比較復雜的情況下,就將其按照上面標准的結構給實現下來。

    

     策略模式的定義:

          1、策略模式定義了算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。

              也個定義,通俗的講,也就是將那些使用的方法風別封裝成獨立的類,然后將這一類使用接口統一管理起來,讓需要使用這些方法的用戶能夠隨時調用他們。上面例子中的戰斗行為就相當於定義中的算法一詞。只是算了個說法而已。

    缺點:

          1、客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道算法或行為的情況。

          2、由於策略模式把每個具體的策略實現都單獨封裝成為類,如果備選的策略很多的話,那么這些類的數目就非常多了。

 

 

 

 

 

 

               


免責聲明!

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



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