天天看點

設計模式(一) 政策模式

    序言

       最近在看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 CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();

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

    2、ThreadPoolExecutor中的四種拒絕政策

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

四、總結

      其實我們平常的代碼中,沒有那麼複雜,隻需要将其中變化的部分給抽取出來,達到複用的目的就行了,這種政策模式一般都是在那種比較複雜的情況下,就将其按照上面标準的結構給實作下來。

    政策模式的定義:

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

              也個定義,通俗的講,也就是将那些使用的方法風别封裝成獨立的類,然後将這一類使用接口統一管理起來,讓需要使用這些方法的使用者能夠随時調用他們。上面例子中的戰鬥行為就相當于定義中的算法一詞。隻是算了個說法而已。

    缺點:

          1、用戶端必須知道所有的政策類,并自行決定使用哪一個政策類。這就意味着用戶端必須了解這些算法的差別,以便适時選擇恰當的算法類。換言之,政策模式隻适用于用戶端知道算法或行為的情況。

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