开发者社区> 芝麻软件> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Head First设计模式之策略模式

简介:   这是学习的第一个设计模式,而书中写的实例相对比较复杂,参考了网上的文章进行总结 一、定义    策略模式(strategy pattern): 定义了算法族, 分别封闭起来, 让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户.    策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换。
+关注继续查看

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

一、定义

   策略模式(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设计模式之目录

  

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Head First设计模式之中介者模式
一、定义 又称为调停者模式,定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显示地相互引用,从而使其耦合性松散,而且可以独立地改变他们之间的交互。 二、结构 组成:   ● 抽象中介者(Mediator)角色:定义统一的接口用于各同事角色之间的通信,其中主要方法是一个(或多个)事件方法。
730 0
Head First设计模式之责任链模式
一、定义   避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。   主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
931 0
Head First设计模式之访问者模式
一、定义 定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。 访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变。
788 0
Head First设计模式之状态模式
一、定义 定义:允许对象在内部状态改变时改变它的行为, 对象看起来好像修改了它的类。 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。 何时使用:代码中包含大量与对象状态有关的条件语句。
890 0
Head First设计模式之工厂模式
一、定义 定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个. 工厂方法让类把实例化推迟到子类 二、结构 1、抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
718 0
Head First设计模式之组合模式
一、定义 将对象组合成树形结构来表现"整体-部分"层次结构。 组合能让客户以一致的方法处理个别对象以及组合对象。 主要部分可以被一致对待问题. 在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。
743 0
Head First设计模式之外观模式
一、定义 外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。 外观模式不只是简化了接口,也将客户从组件的子系统中解耦。 外观和适配器可以包装许多类,但是外观强调的是简化接口,而适配器是为了将接口转换成不同的接口。
702 0
Head First设计模式之模板方法模式
一、定义 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变算法结构的情况下,重定义该算法中的某些特定步骤。 比较通俗的说法,子类决定如何实现算法中的某些步骤,比如两个一连串的操作,操作次序是一样的,有的操作相同,有的不同,将两个连串操作抽象出父类; 子类在相同次序,但具体方法不一样的操作 在父类抽象出来,然后在子类重写实现,达到减少重复代码。
676 0
Head First设计模式之装饰者模式
一、定义 装饰者模式,英文叫Decorator Pattern,在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。
926 0
[Head First设计模式]策略模式
原文:[Head First设计模式]策略模式 系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式——建造者模式 [Head First...
746 0
+关注
芝麻软件
编程语言,框架相关专家
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载