zoukankan      html  css  js  c++  java
  • Head First设计模式之策略模式

      这是学习的第一个设计模式,而书中写的实例相对比较复杂,参考了网上的文章进行总结

    一、定义

       策略模式(strategy pattern): 定义了算法族, 分别封闭起来, 让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户.

       策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

    设计原则一

      找出应用中需要变化之处,把它们独立出来、不要和那些不需要变化的代码混在一起

    设计原则二

      针对接口编程,而不是针对实现编程

    设计原则三

      多用组合、少用继承

     

    二、结构

    策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象负责。策略模式通常把一系列的算法包装到一系列的策略类里面。用一句话慨括策略模式就是——“将每个算法封装到不同的策略类中,使得它们可以互换”。

    下面是策略模式的结构图:

    该模式涉及到三个角色:

    • 环境角色(Context):持有一个Strategy类的引用
    • 抽象策略角色(Strategy):这是一个抽象角色,通常由一个接口或抽象类来实现。此角色给出所有具体策略类所需实现的接口。
    • 具体策略角色(ConcreteStrategy):包装了相关算法或行为。

    三、实现

    以下以计算个人所得税为例

    namespace StrategyPattern
    {
        // 所得税计算策略
        public interface ITaxStragety
        {
            double CalculateTax(double income);
        }
     
        // 个人所得税
        public class PersonalTaxStrategy : ITaxStragety
        {
            public double CalculateTax(double income)
            {
                return income * 0.12;
            }
        }
     
        // 企业所得税
        public class EnterpriseTaxStrategy : ITaxStragety
        {
            public double CalculateTax(double income)
            {
                return (income - 3500) > 0 ? (income - 3500) * 0.045 : 0.0;
            }
        }
     
        public class InterestOperation
        {
            private ITaxStragety m_strategy;
            public InterestOperation(ITaxStragety strategy)
            {
                this.m_strategy = strategy;
            }
     
            public double GetTax(double income)
            {
                return m_strategy.CalculateTax(income);
            }
        }
     
        class App
        {
            static void Main(string[] args)
            {
                // 个人所得税方式
                InterestOperation operation = new InterestOperation(new PersonalTaxStrategy());
                Console.WriteLine("个人支付的税为:{0}", operation.GetTax(5000.00));
     
                // 企业所得税
                operation = new InterestOperation(new EnterpriseTaxStrategy());
                Console.WriteLine("企业支付的税为:{0}", operation.GetTax(50000.00));
     
                Console.Read();
            }
        }
    }

     关于其他例子

    •   被测试网站是一个针对全球很多市场的一个网站,有时同一个测试点,需要我们配置一下网络代理和其它不同的设置来模拟当地市场。

        http://www.cnblogs.com/heqichang/archive/2012/12/13/2815927.html

      

    四、适用场景

      在.NET Framework中也不乏策略模式的应用例子。例如,在.NET中,为集合类型ArrayList和List<T>提供的排序功能,其中实现就利用了策略模式,定义了IComparer接口来对比较算法进行封装,实现IComparer接口的类可以是顺序,或逆序地比较两个对象的大小,具体.NET中的实现可以使用反编译工具查看List<T>.Sort(IComparer<T>)的实现。其中List<T>就是承担着环境角色,而IComparer<T>接口承担着抽象策略角色,具体的策略角色就是实现了IComparer<T>接口的类,List<T>类本身实现了存在实现了该接口的类,我们可以自定义继承与该接口的具体策略类。

    在下面的情况下可以考虑使用策略模式:

    • 一个系统需要动态地在几种算法中选择一种的情况下。那么这些算法可以包装到一个个具体的算法类里面,并为这些具体的算法类提供一个统一的接口。
    • 如果一个对象有很多的行为,如果不使用合适的模式,这些行为就只好使用多重的if-else语句来实现,此时,可以使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象涉及的概念。

    五、优缺点

    模式优点

    • 策略类之间可以自由切换。由于策略类都实现同一个接口,所以使它们之间可以自由切换。
    • 易于扩展。增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码。
    • 避免使用多重条件选择语句,充分体现面向对象设计思想。

    模式缺点

    •  客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

       这点可以考虑使用IOC容器和依赖注入的方式来解决,关于IOC容器和依赖注入(Dependency Inject)的文章可以参考:IoC 容器和Dependency Injection 模式

    •  策略模式会造成很多的策略类。

    欢迎阅读本系列文章:Head First设计模式之目录

      

  • 相关阅读:
    贝叶斯模型
    java的移位和异或运算
    windows下xgboost安装到python
    bagging and boosting
    SVM处理多分类问题
    GO语言语法入门
    [转自SA]浅谈nginx的工作原理和使用
    多线程编程-- part 9 信号量:Semaphore
    多线程编程-- part 8 CyclicBarrier
    多线程编程-- part 7 CountDownLatch
  • 原文地址:https://www.cnblogs.com/xcsn/p/6906533.html
Copyright © 2011-2022 走看看