溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

設計模式系列-策略模式

發(fā)布時間:2020-06-25 12:51:35 來源:網(wǎng)絡 閱讀:1064 作者:wangboyang 欄目:編程語言

      今天下班回家,吃完晚飯后在網(wǎng)上閑逛,看了看電視劇《男人幫》的經(jīng)典臺詞,感覺很經(jīng)典,雖然這個電視劇我早已經(jīng)在上個月就看完了,但是看了看里面的經(jīng)典開場白和臺詞,還是不由自主的伸出大拇指,贊??!

       列舉部分臺詞如下:

      (1)自從我們睜開眼睛看這個世界的第一天起, 我們看到的就只有兩種人,男人和女人。 他們分屬于兩大不同的陣營,為了徹底收服對方,大家互相往死里掐。
      (2)根據(jù)一個遙遠的傳說,說有一種東西叫愛情,可以徹底終結這場戰(zhàn)爭。 于是大家紛紛的趕緊去尋找,趕緊去幻想, 找到頭破血流才發(fā)現(xiàn),原來這個感情也是另一些人在書房里炮制出來的。 于是大家更加絕望,更加痛苦,更加互相的往死里掐。 

        1、場景案例
       尤其是上面這幾句,讓我想起了我一同事(這里用“某某哥”代替)和他女朋友的故事(這里用“某某嫂”代替),一次活動中,某某哥認識了某某嫂,那個一見鐘情呀,簡直是看不見某某嫂就吃不下飯、寫不下代碼呀,在追求中也沒少費工夫。比如:送小禮物,請客吃飯,搞浪漫等等,我們就把這幾個階段分別用代碼模擬一下把!

           ①第一階段贈送小禮物代碼如下:

  1. //第一階段 送小禮物  
  2.     public static void SendGift()  
  3.     {  
  4.         Console.WriteLine("送給女方精美小禮物!");  
  5.     }  
  6.  
  7.     static void Main(string[] args)  
  8.     {  
  9.         //第一階段   
  10.         SendGift();  
  11.     } 

           ② 此時、通過送精美小禮物女方已經(jīng)愿意與男方接觸,這時就可以一起吃飯了,代碼如下:

  1. //第一階段 送小禮物  
  2.  public static void SendGift()  
  3.  {  
  4.      Console.WriteLine("送給女方精美小禮物!");  
  5.  }  
  6.  
  7.  //添加 第二階段 請客吃飯  
  8.  public static void Eat()  
  9.  {  
  10.      Console.WriteLine("請女生吃牛排!");  
  11.  }  
  12.  
  13.  static void Main(string[] args)  
  14.  {  
  15.      //第一階段   
  16.      //SendGift(); //此時第一階段已經(jīng)不需要了所以注銷掉進入第二階段  
  17.  
  18.      //第二階段  
  19.      Eat();  
  20.  } 

         ③ 經(jīng)過之前階段的接觸,兩人已經(jīng)在一起了,在一起就免不了在熱戀中經(jīng)歷浪漫情節(jié),第三階段:制造浪漫、代碼如下:

  1. //第一階段 送小禮物  
  2.       public static void SendGift()  
  3.       {  
  4.           Console.WriteLine("送給女方精美小禮物!");  
  5.       }  
  6.  
  7.       //添加 第二階段 請客吃飯  
  8.       public static void Eat()  
  9.       {  
  10.           Console.WriteLine("請女生吃牛排!");  
  11.       }  
  12.  
  13.       //添加 第三階段 浪漫:燭光晚餐等待女友  
  14.       public static void Romantic()  
  15.       {  
  16.           Console.WriteLine("精心制作了紅酒、晚餐與蠟燭,等待女友回家!");  
  17.       }  
  18.  
  19.       static void Main(string[] args)  
  20.       {  
  21.           //第一階段   
  22.           //SendGift(); //此時第一階段已經(jīng)不需要了所以注銷掉進入第二階段  
  23.  
  24.           //第二階段  
  25.           //Eat(); //此時第二階段也已經(jīng)經(jīng)過,所以注銷掉、進入第三階段  
  26.  
  27.           //第三階段  
  28.           Romantic();  
  29.       }  
             看了某某哥追某某嫂的經(jīng)過后,我們會發(fā)現(xiàn),每當進入一個新階段的時候,我們就需要去修改我們的代碼,加入新的追女策略,并且將main函數(shù)中的調(diào)用修改成進入新的階段,那么我們怎么樣能避免,在進入新階段后不去修改調(diào)用的代碼呢?當然這個肯定難不倒你,代碼如下:
  1. //第一階段 送小禮物  
  2.         public static void SendGift()  
  3.         {  
  4.             Console.WriteLine("送給女方精美小禮物!");  
  5.         }  
  6.  
  7.         //添加 第二階段 請客吃飯  
  8.         public static void Eat()  
  9.         {  
  10.             Console.WriteLine("請女生吃牛排!");  
  11.         }  
  12.  
  13.         //添加 第三階段 浪漫:燭光晚餐等待女友  
  14.         public static void Romantic()  
  15.         {  
  16.             Console.WriteLine("精心制作了紅酒、晚餐與蠟燭,等待女友回家!");  
  17.         }  
  18.  
  19.         static void Main(string[] args)  
  20.         {  
  21.             Console.Write("現(xiàn)在是第幾階段?:");  
  22.             string level = Console.ReadLine(); //代表當前是哪個階段  
  23.             switch (level)  
  24.             {  
  25.                 case "one"://第一階段   
  26.                     SendGift();  
  27.                     break;  
  28.                 case "two"://第二階段  
  29.                     Eat();  
  30.                     break;  
  31.                 case "three"//第三階段  
  32.                     Romantic();  
  33.                     break;  
  34.                 default:  
  35.                     Console.WriteLine("沒這個打算湊什么熱鬧?");  
  36.                     break;  
  37.             }  
  38.         }  
                 這樣我們就解決了在兩人進入新的階段后,無需修改main方法中的代碼!輸出結果如下:

   設計模式系列-策略模式

         那么如果這時兩人已經(jīng)到了談婚論嫁的時候,該怎么辦呢?也就是要在新加入一個階段叫做結婚呢?

          2、引入策略模式

         普通的辦法還是要去新增方法,在修改調(diào)用代碼!那我們有沒有辦法呢?別著急,先看看策略模式、定義如下:“它定義了算法家族,分別封裝起來,讓他們之間可以互相替換,次模式讓算法的變化,不會影響到使用算法的客戶”。

          策略模式類圖如下:

設計模式系列-策略模式

         那么使用策略模式改裝,我們上面場景的類圖如下:

設計模式系列-策略模式

          模擬出了類型那么我們寫代碼當然也就不難啦。

          ① 首先呢,我們需要抽象出來追女孩策略,這個策略里面有一個公共的接口就是去做(也就是行動的意思),例如:送禮物、吃飯、浪漫,都是需要人去做去行動的。

  1. //追女孩策略抽象類  
  2.  public abstract class PursueaGirlStrategy  
  3.  {  
  4.      //追女孩策略中都有一個統(tǒng)一的接口,就是行動。  
  5.      public abstract void Justdoit();  
  6.  }  
          ② 接下來,就是追女孩策略中,各個環(huán)節(jié)策略的實現(xiàn)啦,代碼如下:
  1. //第一階段 送小禮物  
  2.    public class SendGiftStrategy : PursueaGirlStrategy  
  3.    {  
  4.        public override void Justdoit()  
  5.        {  
  6.            Console.WriteLine("送給女方精美小禮物!");  
  7.        }  
  8.    }  
  9.  
  10.    //第二階段 請客吃飯  
  11.    public class EatStrategy : PursueaGirlStrategy  
  12.    {  
  13.        public override void Justdoit()  
  14.        {  
  15.            Console.WriteLine("請女生吃牛排!");  
  16.        }  
  17.    }  
  18.  
  19.    //第三階段 浪漫:燭光晚餐等待女友  
  20.    public class RomanticStrategy : PursueaGirlStrategy  
  21.    {  
  22.        public override void Justdoit()  
  23.        {  
  24.            Console.WriteLine("精心制作了紅酒、晚餐與蠟燭,等待女友回家!");  
  25.        }  
  26.    }  
         ③ 最后就是,承載策略實例,提供統(tǒng)一調(diào)用的策略上下文啦。代碼如下:
  1. //策略的宿主 承載當前需要執(zhí)行的策略  
  2.    public class PursueaGirlContext  
  3.    {  
  4.        SendGiftStrategy staregy;  
  5.        public PursueaGirlContext(SendGiftStrategy strategy)  
  6.        {  
  7.            this.staregy = strategy;  
  8.        }  
  9.  
  10.        //調(diào)用策略的公共接口方法  
  11.        public void ContextJustdoit()  
  12.        {  
  13.            if (this.staregy != null)  
  14.            {  
  15.                this.staregy.Justdoit();  
  16.            }  
  17.        }  
  18.  
  19.    }  
  20.       main方法將來調(diào)用如下:  
  21.  
  22.  static void Main(string[] args)  
  23.        {  
  24.            //定義追女孩策略上下文對象  
  25.            PursueaGirlContext context = null;  
  26.            Console.Write("現(xiàn)在是第幾階段?:");  
  27.            string level = Console.ReadLine(); //代表當前是哪個階段  
  28.            switch (level)  
  29.            {  
  30.                case "one"://第一階段   
  31.                    context = new PursueaGirlContext(new SendGiftStrategy());  
  32.                    break;  
  33.                case "two"://第二階段  
  34.                    context = new PursueaGirlContext(new EatStrategy());  
  35.                    break;  
  36.                case "three"//第三階段  
  37.                    context = new PursueaGirlContext(new RomanticStrategy());  
  38.                    break;  
  39.                default:  
  40.                    Console.WriteLine("沒這個打算湊什么熱鬧?");  
  41.                    break;  
  42.            }  
  43.  
  44.            //統(tǒng)一的策略調(diào)用模式  
  45.            context.ContextJustdoit();  
  46.        }  
          好的,策略模式與我們的場景先告一段落把。這個時候可能有的人就會問啦,策略模式跟工廠模式很想啊,都是提供一個統(tǒng)一的接口,有不同的實例去實例化。那么我們來看看策略模式與工廠模式的區(qū)別吧。

          3、策略模式與工廠模式的區(qū)別

          概念上理解:

                     ① 策略模式:是告訴上下文,我需要去做什么,至于使用怎么實現(xiàn),需要上下文去使用當前對應的策略去實現(xiàn)。例如:項目經(jīng)理(客戶端)說:“我要實現(xiàn)即時消息功能”,那么我們程序員(上下文)就需要去尋找對應的策略(開發(fā)即時消息模塊的策略)去實現(xiàn)。

                     ②工廠模式:是告訴工廠,此時我需要什么部件你去給我制造,例如:開發(fā)及時消息模塊,我需要JS的彈出框,我就會告訴UI組(工廠),給我做一個JS彈出框,要求模仿EXT的。

          4、策略與工廠談戀愛

           那么了解了他們之間的區(qū)別后,我們再來看上面策略模式實現(xiàn)的一個問題,例如:需要加入結婚策略時,還是需要增加結婚策略類,并且修改客戶端(MAIN方法)中的調(diào)用代碼。那么我們把提供使用策略的代碼放到工廠中呢?這樣我們以后就只需要增加新策略修改工廠就行啦!客戶端就不用修改了。

           ①工廠代碼代碼如下:

  1. //提供策略的工廠  
  2.     public class FactoryStrategy  
  3.     {  
  4.         //根據(jù)客戶端參數(shù)創(chuàng)建策略  
  5.         public static PursueaGirlContext GetStrategy(string level)  
  6.         {  
  7.             //定義追女孩策略上下文對象  
  8.             PursueaGirlContext context = null;  
  9.             switch (level)  
  10.             {  
  11.                 case "one"://第一階段  禮物  
  12.                     context = new PursueaGirlContext(new SendGiftStrategy());  
  13.                     break;  
  14.                 case "two"://第二階段 吃飯  
  15.                     context = new PursueaGirlContext(new EatStrategy());  
  16.                     break;  
  17.                 case "three"//第三階段 浪漫  
  18.                     context = new PursueaGirlContext(new RomanticStrategy());  
  19.                     break;  
  20.                 case "four"://第四階段 結婚  
  21.                     context = new PursueaGirlContext(new MarriedStrategy());  
  22.                     break;  
  23.                 default:  
  24.                     context = null;  
  25.                     break;  
  26.             }  
  27.             return context;  
  28.         }  
  29.     }  
           ② 有了工廠后的客戶端(main)代碼如下:
  1. static void Main(string[] args)  
  2.        {  
  3.             
  4.            Console.Write("現(xiàn)在是第幾階段?:");  
  5.            string level = Console.ReadLine(); //代表當前是哪個階段  
  6.  
  7.            //定義追女孩策略上下文對象  
  8.            PursueaGirlContext context = FactoryStrategy.GetStrategy(level);  
  9.  
  10.            //統(tǒng)一的策略調(diào)用模式  
  11.            context.ContextJustdoit();  
  12.        }  
 
           ③ 完整代碼如下:
  1. //追女孩策略抽象類  
  2.     public abstract class PursueaGirlStrategy  
  3.     {  
  4.         //追女孩策略中都有一個統(tǒng)一的接口,就是行動。  
  5.         public abstract void Justdoit();  
  6.     }  
  7.  
  8.     //第一階段 送小禮物  
  9.     public class SendGiftStrategy : PursueaGirlStrategy  
  10.     {  
  11.         public override void Justdoit()  
  12.         {  
  13.             Console.WriteLine("送給女方精美小禮物!");  
  14.         }  
  15.     }  
  16.  
  17.     //第二階段 請客吃飯  
  18.     public class EatStrategy : PursueaGirlStrategy  
  19.     {  
  20.         public override void Justdoit()  
  21.         {  
  22.             Console.WriteLine("請女生吃牛排!");  
  23.         }  
  24.     }  
  25.  
  26.     //第三階段 浪漫:燭光晚餐等待女友  
  27.     public class RomanticStrategy : PursueaGirlStrategy  
  28.     {  
  29.         public override void Justdoit()  
  30.         {  
  31.             Console.WriteLine("精心制作了紅酒、晚餐與蠟燭,等待女友回家!");  
  32.         }  
  33.     }  
  34.  
  35.     //添加第四階段 結婚  
  36.     public class MarriedStrategy : PursueaGirlStrategy  
  37.     {  
  38.         public override void Justdoit()  
  39.         {  
  40.             Console.WriteLine("兩人民政局領證!");  
  41.         }  
  42.     }  
  43.  
  44.     //提供策略的工廠  
  45.     public class FactoryStrategy  
  46.     {  
  47.         //根據(jù)客戶端參數(shù)創(chuàng)建策略  
  48.         public static PursueaGirlContext GetStrategy(string level)  
  49.         {  
  50.             //定義追女孩策略上下文對象  
  51.             PursueaGirlContext context = null;  
  52.             switch (level)  
  53.             {  
  54.                 case "one"://第一階段  禮物  
  55.                     context = new PursueaGirlContext(new SendGiftStrategy());  
  56.                     break;  
  57.                 case "two"://第二階段 吃飯  
  58.                     context = new PursueaGirlContext(new EatStrategy());  
  59.                     break;  
  60.                 case "three"//第三階段 浪漫  
  61.                     context = new PursueaGirlContext(new RomanticStrategy());  
  62.                     break;  
  63.                 case "four"://第四階段 結婚  
  64.                     context = new PursueaGirlContext(new MarriedStrategy());  
  65.                     break;  
  66.                 default:  
  67.                     context = null;  
  68.                     break;  
  69.             }  
  70.             return context;  
  71.         }  
  72.     }  
  73.  
  74.     //策略的宿主 承載當前需要執(zhí)行的策略  
  75.     public class PursueaGirlContext  
  76.     {  
  77.         PursueaGirlStrategy staregy;  
  78.         public PursueaGirlContext(PursueaGirlStrategy strategy)  
  79.         {  
  80.             this.staregy = strategy;  
  81.         }  
  82.  
  83.         //調(diào)用策略的公共接口方法  
  84.         public void ContextJustdoit()  
  85.         {  
  86.             if (this.staregy != null)  
  87.             {  
  88.                 this.staregy.Justdoit();  
  89.             }  
  90.         }  
  91.  
  92.     }  
  93.     static void Main(string[] args)  
  94.         {  
  95.              
  96.             Console.Write("現(xiàn)在是第幾階段?:");  
  97.             string level = Console.ReadLine(); //代表當前是哪個階段  
  98.  
  99.             //定義追女孩策略上下文對象  
  100.             PursueaGirlContext context = FactoryStrategy.GetStrategy(level);  
  101.  
  102.             //統(tǒng)一的策略調(diào)用模式  
  103.             context.ContextJustdoit();  
  104.         }  
        這樣我們以后如果有新的策略只需要增加新的策略類,修改工廠即可,那么細心的朋友問了,這樣只不過是把修改客戶端移到工廠里面了,將來還是需要工廠,沒關系徹底解決調(diào)用修改的話,我們將來可以利用反射!以后不管修改還是新增我們都能很好的去應對了。
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI