zoukankan      html  css  js  c++  java
  • 设计模式Strategy 策略模式

      所谓策略模式(Strategy Pattern),就是将策略 (算法) 封装为一个对象,易于相互替换,如同 USB 设备一样可即插即用;如果将策略、具体的算法和行为,编码在某个类或客户程序内部,将导至事后的修改和扩展不易。
      当有多种「策略」时,通常的作法就是将这些个策略,和这些策略的算法、行为,分别封装在各个类中,并让这些类,去继承某个公用的抽象类或接口。接着在客户 程序中,就可动态引用,且易于更换这些不同的「策略」,不会因为日后添加、修改了某一个「策略」,就得重新修改、编译多处的源代码。此即为一种「封装变化 点」的做法,将常会变化的部分进行抽象、定义为接口,亦即实现「面向接口编程」的概念。且客户程序 (调用者) 只须知道接口的外部定义即可,具体的实现则无须理会。
       策略模式(Strategy Pattern)在外形上与状态模式很相似,但在意图上有些不同。其意图是使这些算法可以相互替换,并提供一种方法来选择最合适的算法。
       策略模式(Strategy Pattern)的UML图如下:

                            
    在策略模式里主要有三种角色:环境角色、抽象策略角色和具体策略角色
    1、环境(Context)角色:持有一个抽象策略(Strategy)角色的引用。也叫上下文。
    2、抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或一个抽象类来实现。
    3、具体策略(ConcreteStrategy)角色:包装了相应的算法和行为。
    下面我们用代码来示例策略模式,程序如下图:

                            
    一、策略模式基本思路示例

    1、环境(Context)角色:


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

    namespace
     MyStrategyPattern
    {
        
    #region 定义Context类

        
    class Context
        {
            
    private
     Strategy _strategy;

            
    #region 构造函数

            
    public Context(Strategy strategy)
            {
                
    this._strategy =
     strategy;
            }
            
    #endregion


            
    #region 定义算法接口
            
    //具体的算法由传入的strategy对象的AlgorithmInterface方法来实现
            public void ContextInterface()
            {
                _strategy.AlgorithmInterface();
           
     }
            
    #endregion

        }
        
    #endregion
    }
    2、抽象策略(Strategy)角色:

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

    namespace MyStrategyPattern
    {
        
    #region 抽象策略类Strategy,定义了具体策略类的共有算法接口
        
    abstract  class Strategy
        {
            
    public abstract void AlgorithmInterface();
        }
        
    #endregion
    }
    3、具体策略(ConcreteStrategy)角色:

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

    namespace MyStrategyPattern

        
    //定义了一系列的具体策略类,它们继承自抽象策略类

        
    class ConcreteStrategyA : Strategy
        {
            
    public override void AlgorithmInterface()
            {
                Console.WriteLine(
    "使用了算法A来处理Context对象");
            }
        }

        
    class ConcreteStrategyB : Strategy
        {
            
    public override void AlgorithmInterface()
            {
                Console.WriteLine(
    "使用了算法B来处理Context对象");
            }
        }

        
    class ConcreteStrategyC : Strategy
        {
            
    public override void AlgorithmInterface()
            {
                Console.WriteLine(
    "使用了算法C来处理Context对象");
            }
        }
    }
    4、客户应用代码

                #region 基本思路示例
                Console.WriteLine(
    "----策略模式基本思路示例----");
                Context context;
                
    //调用不同的算法来处理对象,算法的差异在Context传参时(new ConcreteStrategyA())决定
                context = new Context(new ConcreteStrategyA());
                context.ContextInterface();

                context 
    = new Context(new ConcreteStrategyB());
                context.ContextInterface();

                context 
    = new Context(new ConcreteStrategyC());
                context.ContextInterface();


                
    #endregion

    二、求和计算的策略模式示例
    1、环境(Context)角色:CalculateContext.


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

    namespace
     MyStrategyPattern
    {
        
    class
     CalculateContext
        {
            ICalculateStrategy _strategy;
            
    public
     CalculateContext(ICalculateStrategy strategy)
            {
                _strategy 
    =
     strategy;
            }

            
    public void PerformCalculation(List<int>
     list)
            {
                Console.WriteLine(
    string.Format("对列表中所有整数求和,结果为:{0}"
    , _strategy.Sum(list)));
            }
        }
    }

    2、抽象策略(Strategy)角色:ICalculateStrategy


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

    namespace MyStrategyPattern
    {
        
    interface  ICalculateStrategy
        {
            
    int Sum(List<int> list);
        }
    }

    3、具体策略(ConcreteStrategy)角色:CalculateStrategies



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

    namespace MyStrategyPattern
    {
        
    #region 方法A
        
    class ConcreteCalculateStrategyA : ICalculateStrategy
        {
            
    //利用List的Sum功能对List中整数求和
            public int Sum(List<int> list)
            {
                Console.WriteLine(
    "----。使用方法A进行求和----");
                
    return list.Sum();
            }
        }
        
    #endregion

        
    #region 方法B
        
    class ConcreteCalculateStrategyB : ICalculateStrategy
        {
            
    //使用传统的遍历方法,对List中整数求和
            public int Sum(List<int> list)
            {
                Console.WriteLine(
    "----。使用方法B进行求和----");
                
    int result = 0;
                
    foreach(int value in list)
                {
                    result 
    += value;
                }
                
    return result;
            }
        }
        
    #endregion


    }

    4、客户应用代码


               #region 求和计算的策略模式示例
                Console.WriteLine(
    "\n\n----求和计算的策略模式示例----");
                List
    <int> lst = new List<int>
    ();
                lst.Add(
    3
    );
                lst.Add(
    6
    );
                lst.Add(
    8
    );
                lst.Add(
    9
    );

                CalculateContext caltext;
                caltext 
    = new CalculateContext(new
     ConcreteCalculateStrategyA());
                caltext.PerformCalculation(lst);

                caltext 
    = new CalculateContext(new
     ConcreteCalculateStrategyB());
                caltext.PerformCalculation(lst);

                Console.ReadKey();

                
    #endregion

    效果如下图:
                            

    总结:

    Strategy Pattern 适用的情景:
    1、应用中的许多类,在解决某些问题时很相似,但实现的行为有所差异。比如:不同功能的程序,都可能要用到「排序」算法。
    2、根据运行环境的不同,需要采用不同的算法。比如:在手机、PC 计算机上,因硬件等级不同,必须采用不同的排序算法。
    3、针对给定的目的,存在多种不同的算法,且我们可用代码实现算法选择的标准。
    4、需要封装复杂的数据结构。比如:特殊的加密算法,客户程序仅需要知道调用的方式即可。
    5、同上,算法中的罗辑和使用的数据,应该与客户程序隔离时。

    Strategy Pattern 的优点:
    1、简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独做测试。
    2、避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
    3、高内聚、低偶合。

    Strategy Pattern 的缺点:
    1、因为每个具体策略都会产生一个新类,所以会增加需要维护的类的数量。
    2、选择所用具体实现的职责由客户程序承担,并转给 Context 对象,并没有解除客户端需要选择判断的压力。
    3、若要减轻客户端压力,或程序有特殊考量,还可把 Strategy 与 Simple Factory 两种 Pattern 结合,即可将选择具体算法的职责改由 Context 来承担,亦即将具体的算法,和客户程序做出隔离。

    前往:设计模式学习笔记清单
  • 相关阅读:
    解析xml
    序列化为xml
    aspose.cells excel表格导入导出
    文件下载
    jquery拼接和拆分字符串,并加入特殊符号
    VC Windows系统服务创建代码
    Lua 基础知识-面向对象
    iOS 网络与多线程--8.百度地图的使用(调用系统浏览器)
    iOS 网络与多线程--7.Performselector消息处理方法
    iOS 网络与多线程--6.下载并保存网络图片
  • 原文地址:https://www.cnblogs.com/smallfa/p/1609456.html
Copyright © 2011-2022 走看看