文章出處

經典的策略模式如下圖所示:

image

讓我解釋一下這幅圖的含義,IContext是上下文的接口類,IStrategy是策略的接口,IStrategy依賴于IContext,也就是IContext里面存有一個IStrategy的策略字段。

其實策略模式說白了,就像諸葛亮給劉備的錦囊妙計一樣,遇到一種具體的情況,采取一種相應的策略。也就像我們平時會觀察天氣,根據今天有沒有下雨,選擇要不要打傘,下雨的話,那么打傘;不下雨就不打傘。

下面我們用代碼來演示一下經典的策略模式。我們將要做的是,從一個數組中提取一個值,這個值的提取要根據用戶的選擇,也就是我們要根據用戶的選擇提取對應的值。假設用戶有三種選擇,選最大值,最小值,選第一個值。

1、首先我們要實現公共接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BangWorks.PractcalPattern.StategyPattern.Classic
{
    interface IStrategy
    {
        /// <summary>
        /// 按照算法的要求,將數據提取出來
        /// </summary>
        /// <param name="Data">數組</param>
        /// <returns></returns>
        int PickUp(int[] Data);
    }
    interface IContext
    {
        IStrategy Strategy { get; set; }
        int GetData(int[] data);
        
    }
}

2、實現相應的策略類

/// <summary>
        /// 取最大值
        /// </summary>
        class DescentSortStrategy:IStrategy
        {
            int IStrategy.PickUp(int[] Data)
            {   Array.Sort<int>(Data);
                return Data[Data.Length-1];
              
            }
        }
        /// <summary>
        /// 取第一個值
        /// </summary>
        class FirstDataStrategy:IStrategy
        {

            public int PickUp(int[] Data)
            {
                return Data[0];
            }
        }
        /// <summary>
        /// 取最小值
        /// </summary>
        class AscentStrategy:IStrategy
        {
            int IStrategy.PickUp(int[] Data)
            {
                Array.Sort<int>(Data);
                return Data[0];
            }
        }

3、最后,我們利用策略模式來切換策略

/// <summary>
        ///GetData 的測試
        ///</summary>
        [TestMethod()]
        public void GetDataTest()
        {
            IStrategy mStrategy = new FirstDataStrategy();
            
            IContext target = CreateIContext(); 
            int[] data = new int[]{7,2,5,8,0,1};

            //切換成取第一個值的
            target.Strategy = mStrategy;
            int expected = 7; 
            int actual;
            actual = target.GetData(data);
            Assert.AreEqual(expected, actual);
            //切換成取最小值的
            target.Strategy = new AscentStrategy();
            expected = 0; 
            actual = target.GetData(data);
            Assert.AreEqual(expected, actual);

            //切換成取最大值的
            target.Strategy = new DescentSortStrategy();
            expected = 8;
            actual = target.GetData(data);
            Assert.AreEqual(expected, actual);
        }

最后附上完整的單元測試類

  1 using BangWorks.PractcalPattern.StategyPattern.Classic;
  2 using Microsoft.VisualStudio.TestTools.UnitTesting;
  3 using System;
  4 
  5 namespace BangWork.PractcalPattern.Concept.InderTest
  6 {
  7     
  8     
  9     /// <summary>
 10     ///這是 IContextTest 的測試類,旨在
 11     ///包含所有 IContextTest 單元測試
 12     ///</summary>
 13     [TestClass()]
 14     public class IContextTest:IContext
 15     {
 16         /// <summary>
 17         /// 取最大值
 18         /// </summary>
 19         class DescentSortStrategy:IStrategy
 20         {
 21             int IStrategy.PickUp(int[] Data)
 22             {   Array.Sort<int>(Data);
 23                 return Data[Data.Length-1];
 24               
 25             }
 26         }
 27         /// <summary>
 28         /// 取第一個值
 29         /// </summary>
 30         class FirstDataStrategy:IStrategy
 31         {
 32 
 33             public int PickUp(int[] Data)
 34             {
 35                 return Data[0];
 36             }
 37         }
 38         /// <summary>
 39         /// 取最小值
 40         /// </summary>
 41         class AscentStrategy:IStrategy
 42         {
 43             int IStrategy.PickUp(int[] Data)
 44             {
 45                 Array.Sort<int>(Data);
 46                 return Data[0];
 47             }
 48         }
 49         private TestContext testContextInstance;
 50 
 51         /// <summary>
 52         ///獲取或設置測試上下文,上下文提供
 53         ///有關當前測試運行及其功能的信息。
 54         ///</summary>
 55         public TestContext TestContext
 56         {
 57             get
 58             {
 59                 return testContextInstance;
 60             }
 61             set
 62             {
 63                 testContextInstance = value;
 64             }
 65         }
 66 
 67         #region 附加測試特性
 68         // 
 69         //編寫測試時,還可使用以下特性:
 70         //
 71         //使用 ClassInitialize 在運行類中的第一個測試前先運行代碼
 72         //[ClassInitialize()]
 73         //public static void MyClassInitialize(TestContext testContext)
 74         //{
 75         //}
 76         //
 77         //使用 ClassCleanup 在運行完類中的所有測試后再運行代碼
 78         //[ClassCleanup()]
 79         //public static void MyClassCleanup()
 80         //{
 81         //}
 82         //
 83         //使用 TestInitialize 在運行每個測試前先運行代碼
 84         //[TestInitialize()]
 85         //public void MyTestInitialize()
 86         //{
 87         //}
 88         //
 89         //使用 TestCleanup 在運行完每個測試后運行代碼
 90         //[TestCleanup()]
 91         //public void MyTestCleanup()
 92         //{
 93         //}
 94         //
 95         #endregion
 96 
 97 
 98         internal virtual IContext CreateIContext()
 99         {
100             // TODO: 實例化相應的具體類。
101             IContext target = new IContextTest();
102             return target;
103         }
104 
105         /// <summary>
106         ///GetData 的測試
107         ///</summary>
108         [TestMethod()]
109         public void GetDataTest()
110         {
111             IStrategy mStrategy = new FirstDataStrategy();
112             
113             IContext target = CreateIContext(); 
114             int[] data = new int[]{7,2,5,8,0,1};
115 
116             //切換成取第一個值的
117             target.Strategy = mStrategy;
118             int expected = 7; 
119             int actual;
120             actual = target.GetData(data);
121             Assert.AreEqual(expected, actual);
122             //切換成取最小值的
123             target.Strategy = new AscentStrategy();
124             expected = 0; 
125             actual = target.GetData(data);
126             Assert.AreEqual(expected, actual);
127 
128             //切換成取最大值的
129             target.Strategy = new DescentSortStrategy();
130             expected = 8;
131             actual = target.GetData(data);
132             Assert.AreEqual(expected, actual);
133         }
134 
135         /// <summary>
136         ///Strategy 的測試
137         ///</summary>
138         [TestMethod()]
139         public void StrategyTest()
140         {
141             IContext target = CreateIContext(); // TODO: 初始化為適當的值
142             IStrategy expected = null; // TODO: 初始化為適當的值
143             IStrategy actual;
144             target.Strategy = expected;
145             actual = target.Strategy;
146             Assert.AreEqual(expected, actual);
147             Assert.Inconclusive("驗證此測試方法的正確性。");
148         }
149 
150         public IStrategy Strategy
151         {
152             get;
153             set;
154         }
155 
156         public int GetData(int[] data)
157         {
158             return this.Strategy.PickUp(data);
159         }
160     }
161 }
完整策略模式單元測試類

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()