策略模式

经典的策略模式如下图所示:

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 }
完整策略模式单元测试类

 

posted @ 2013-08-27 17:17  陈哈哈  阅读(347)  评论(0编辑  收藏  举报