定义

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

UML

优点

  1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
  2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
  3. 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。

缺点

  1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
  2. 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。

应用场景

  1. 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
  2. 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
  3. 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

示例

考虑一个销售的场景,针对不同的客户销售的产品有不同的优惠。

Java

 public class Main
{
public static void main(String[] args)
{
//1:选择并创建需要使用的策略对象
Strategy strategy = new LargeCustomerStrategy();
//2:创建上下文
Price ctx = new Price(strategy);
//3:计算报价
double quote = ctx.quote(1000);
System.out.println("向客户报价:" + quote);
} /**
* 价格管理,主要完成计算向客户所报价格的功能
*/
public static class Price
{
/**
* 持有一个具体的策略对象
*/
private Strategy strategy = null; /**
* 构造方法,传入一个具体的策略对象
* @param aStrategy 具体的策略对象
*/
public Price(Strategy aStrategy)
{
this.strategy = aStrategy;
} /**
* 报价,计算对客户的报价
* @param goodsPrice 商品销售原价
* @return 计算出来的,应该给客户报的价格
*/
public double quote(double goodsPrice)
{
return this.strategy.calcPrice(goodsPrice);
}
} /**
* 策略,定义计算报价算法的接口
*/
public interface Strategy
{
/**
* 计算应报的价格
* @param goodsPrice 商品销售原价
* @return 计算出来的,应该给客户报的价格
*/
double calcPrice(double goodsPrice);
} /**
* 具体算法实现,为新客户或者是普通客户计算应报的价格
*/
public static class NormalCustomerStrategy implements Strategy
{
public double calcPrice(double goodsPrice)
{
System.out.println("对于新客户或者是普通客户,没有折扣");
return goodsPrice;
}
} /**
* 具体算法实现,为老客户计算应报的价格
*/
public static class OldCustomerStrategy implements Strategy
{
public double calcPrice(double goodsPrice)
{
System.out.println("对于老客户,统一折扣5%");
return goodsPrice * (1 - 0.05);
}
} /**
* 具体算法实现,为大客户计算应报的价格
*/
public static class LargeCustomerStrategy implements Strategy
{
public double calcPrice(double goodsPrice)
{
System.out.println("对于大客户,统一折扣10%");
return goodsPrice * (1 - 0.1);
}
}
}

行为类模式(九):策略(Strategy)的更多相关文章

  1. 行为型设计模式之模板方法(TEMPLATE METHOD)模式 ,策略(Strategy )模式

    1 模板方法(TEMPLATE METHOD)模式: 模板方法模式把我们不知道具体实现的步聚封装成抽象方法,提供一些按正确顺序调用它们的具体方法(这些具体方法统称为模板方法),这样构成一个抽象基类.子 ...

  2. 设计模式C++实现(1)——策略(Strategy)模式

    目录 策略模式 应用案例 实现的关键 Talk is cheap,let's See The Code 设计思想 参考 策略模式 策略模式定义了一系列算法和行为(也就是策略),他们可以在运行时相互替换 ...

  3. 策略(strategy)模式

    Head First一书中对于策略(strategy)模式的正式定义是:策略模式定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户. 为了介绍这个算法,书中讲了 ...

  4. C++设计模式实现--策略(Strategy)模式

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/L_Andy/article/details/30489331 一. 举例说明 曾经做了一个程序,程序 ...

  5. Java 实现策略(Strategy)模式

    策略模式:行为型模式 将同一行为,不同的处理算法分别封装起来.让它们之间能够互相替换 1. 定义一个超类型接口,及 行为方法 2. 定义不同的实现类,实现该行为的 不同的算法 /** * 策略模式:针 ...

  6. 设计模式 策略-Strategy,装饰-Decorator,观察者-Observer

    重温了Head First 3个设计模式.提炼一下思想,笔记如下. 策略-Strategy 当一个类或类族中重复实现某些同类的方法(behavior)时,考虑使用策略模式. 该模式是将Behavior ...

  7. Provider Pattern提供者模式和策略模式

    http://www.codeproject.com/Articles/18222/Provider-Pattern Introduction Provider pattern is one of t ...

  8. Android设计模式之命令模式、策略模式、模板方法模式

    命令模式是其它很多行为型模式的基础模式.策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同.下面来谈谈这三个模式. 命令模式 将一个请求封装为一个对象,从 ...

  9. GoF23种设计模式之行为型模式之策略模式

    传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 1概述           定义一系列算法,把它们一个个都封装起来,并且让它们可以相互 ...

  10. 策略模式、策略模式与Spring的碰撞

    策略模式是GoF23种设计模式中比较简单的了,也是常用的设计模式之一,今天我们就来看看策略模式. 实际案例 我工作第三年的时候,重构旅游路线的机票查询模块,旅游路线分为四种情况: 如果A地-B地往返都 ...

随机推荐

  1. python 之模块之 xml.dom.minidom解析xml

    # -*- coding: cp936 -*- #python 27 #xiaodeng #python 之模块之 xml.dom.minidom解析xml #http://www.cnblogs.c ...

  2. nno Setup入门(一)——最简单的安装脚本

    一个最简单的安装脚本: 1.最简单的安装文件脚本: [setup] AppName=Test AppVerName=TEST DefaultDirName="E:\TEST" Ap ...

  3. VS2017写的exe调用Delphi 7写的DLL

    公司有个很古老的系统,代码量很大,并且稳定线上运行10几年,这系统是公司的核心,公司收入基本靠它,系统几乎都是Delphi 7写的,要重写是不可能的.因为Delphi 7编译出来的DLL默认的导出符号 ...

  4. SQL SERVER 2008 “阻止保存要求重新创建表的更改”

    在SQL SERVER2008中,新建数据表以后,若再对该表进行更改,则会出现警告信息“不允许保存更改 阻止保存要求重新创建表的更改”,等等,需要进行一下设置: 工具--->选项--->D ...

  5. 【CAS单点登录视频教程】 第03集 -- 配置 tomcat的 ssl

    目录 ----------------------------------------- [CAS单点登录视频教程] 第06集[完] -- Cas认证 学习 票据认证FormsAuthenticati ...

  6. (原)ubuntu挂载及开机自动挂载网络端的文件夹的方法

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/7160792.html 参考网址: http://blog.csdn.net/tlight/articl ...

  7. 内存问题排查工具 --- valgrind

    1. 概述 2. Valgrind 3. 内存泄漏监测 3.1. 示例代码 3.2. 编译它 3.3. 用Valgrind监测进程的内存泄漏 4. 悬挂指针 4.1. 示例代码 4.2. Valgri ...

  8. 从零实现Lumen-JWT扩展包(序):前因

    转自:https://zhuanlan.zhihu.com/p/22531819?refer=lsxiao 最近这段时间我寻思着把几个月前爬下来的6万多首诗词曲文做成一个API,免费开放给大家用. 这 ...

  9. MM bound 与 Jensen's inequality

    MM bound 与 Jensen's inequality 简森不等式 在使用最大似然估计方法求解模型最优解的时候,如果使用梯度下降(GD or SGD)或者梯度上升(GA or SGA),可能收敛 ...

  10. 线程同步之mutex和Semaphore

    表示之前对semaphore信号量木有神码概念. 比较纳闷这玩意要干嘛,好吧继续stackflow: Mutex can be released only by thread that had acq ...