定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化;

下面给出策略模式的类图,引自百度百科。

策略模式在LZ第一次接触到的时候,LZ是这么理解的,就是如果我们想往一个方法当中插入随便一段代码的话,就是策略模式。即如下形式。

public class MyClass {public void myMethod(){System.out.println("方法里的代码");//LZ想在这插入一段代码,而且这个代码是可以改变的,想怎么变就怎么变System.out.println("方法里的代码");}
}

在JAVA中,接口可以满足LZ的这一过分要求,我们可以设计一个接口,并当做参数传进去,就能达到这个效果了。我们来看,先定义一个接口。

public interface MyInterface {//我想插入的代码void insertCode();}

将原来的类改成这样,传递一个接口进去。

public class MyClass {public void myMethod(MyInterface myInterface){System.out.println("方法里的代码");//你看我是不是插进来一段代码?而且这段代码是可以随便改变的myInterface.insertCode();System.out.println("方法里的代码");}
}

我们只要实现了MyInterface这个接口,在insertCode方法中写入我们想要插进去的代码,再将这个类传递给myMethod方法,就可以将我们随手写的代码插到这个方法当中。比如这样。

class InsertCode1 implements MyInterface{public void insertCode() {System.out.println("我想插进去的代码,第一种");}}class InsertCode2 implements MyInterface{public void insertCode() {System.out.println("我想插进去的代码,第二种");}}

这样我们在调用myMethod方法时就可以随意往里面插入代码了,比如。

//客户端调用
public class Client {public static void main(String[] args) {MyClass myClass = new MyClass();myClass.myMethod(new InsertCode1());System.out.println("--------------------");myClass.myMethod(new InsertCode2());}}

那么运行出来的结果就是我们成功的将两端代码插入到了myMethod方法中,以上所讲的算是JAVA中一种技术层面的实现,就是传入一个接口,封装代码。那么既然谈到设计模式,就要有设计模式的应用场景,有关策略模式,所产生的形式就和上述是一模一样的,只是我们适当的给予模式的应用场景,就会让它变的更有价值。

上面的例子代码清晰但却理解起来很生硬,下面LZ举一个具有实际意义的例子。

就比如我们要做一个商店的收银系统,这个商店有普通顾客,会员,超级会员以及金牌会员的区别,针对各个顾客,有不同的打折方式,并且一个顾客每在商店消费1000就增加一个级别,那么我们就可以使用策略模式,因为策略模式描述的就是算法的不同,而且这个算法往往非常繁多,并且可能需要经常性的互相替换。

这里我们举例就采用最简单的,以上四种顾客分别采用原价,八折,七折和半价的收钱方式。

那么我们首先要有一个计算价格的策略接口,如下。

public interface CalPrice {//根据原价返回一个最终的价格Double calPrice(Double originalPrice);}

下面我们给出四个计算方式。

class Common implements CalPrice{public Double calPrice(Double originalPrice) {return originalPrice;}}
class Vip implements CalPrice{public Double calPrice(Double originalPrice) {return originalPrice * 0.8;}}
class SuperVip implements CalPrice{public Double calPrice(Double originalPrice) {return originalPrice * 0.7;}}
class GoldVip implements CalPrice{public Double calPrice(Double originalPrice) {return originalPrice * 0.5;}}

以上四种计算方式非常清晰,分别是原价,八折,七折和半价。下面我们看客户类,我们需要客户类帮我们完成客户升级的功能。

//客户类
public class Customer {private Double totalAmount = 0D;//客户在本商店消费的总额private Double amount = 0D;//客户单次消费金额private CalPrice calPrice = new Common();//每个客户都有一个计算价格的策略,初始都是普通计算,即原价//客户购买商品,就会增加它的总额public void buy(Double amount){this.amount = amount;totalAmount += amount;if (totalAmount > 3000) {//3000则改为金牌会员计算方式calPrice = new GoldVip();}else if (totalAmount > 2000) {//类似calPrice = new SuperVip();}else if (totalAmount > 1000) {//类似calPrice = new Vip();}}//计算客户最终要付的钱public Double calLastAmount(){return calPrice.calPrice(amount);}
}

下面我们看客户端调用,系统会帮我们自动调整收费策略。

//客户端调用
public class Client {public static void main(String[] args) {Customer customer = new Customer();customer.buy(500D);System.out.println("客户需要付钱:" + customer.calLastAmount());customer.buy(1200D);System.out.println("客户需要付钱:" + customer.calLastAmount());customer.buy(1200D);System.out.println("客户需要付钱:" + customer.calLastAmount());customer.buy(1200D);System.out.println("客户需要付钱:" + customer.calLastAmount());}}

           运行以后会发现,第一次是原价,第二次是八折,第三次是七折,最后一次则是半价。我们这样设计的好处是,客户不再依赖于具体的收费策略,依赖于抽象永远是正确的。不过上述的客户类实在有点难看,尤其是buy方法,我们可以使用简单工厂来稍微改进一下它。我们建立如下策略工厂。
//我们使用一个标准的简单工厂来改进一下策略模式
public class CalPriceFactory {private CalPriceFactory(){}//根据客户的总金额产生相应的策略public static CalPrice createCalPrice(Customer customer){if (customer.getTotalAmount() > 3000) {//3000则改为金牌会员计算方式return new GoldVip();}else if (customer.getTotalAmount() > 2000) {//类似return new SuperVip();}else if (customer.getTotalAmount() > 1000) {//类似return new Vip();}else {return new Common();}}
}

这样我们就将制定策略的功能从客户类分离了出来,我们的客户类可以变成这样。

//客户类
public class Customer {private Double totalAmount = 0D;//客户在本商店消费的总额private Double amount = 0D;//客户单次消费金额private CalPrice calPrice = new Common();//每个客户都有一个计算价格的策略,初始都是普通计算,即原价//客户购买商品,就会增加它的总额public void buy(Double amount){this.amount = amount;totalAmount += amount;/* 变化点,我们将策略的制定转移给了策略工厂,将这部分责任分离出去 */calPrice = CalPriceFactory.createCalPrice(this);}//计算客户最终要付的钱public Double calLastAmount(){return calPrice.calPrice(amount);}public Double getTotalAmount() {return totalAmount;}public Double getAmount() {return amount;}}

现在比之前来讲,我们的策略模式更加灵活一点,但是相信看过LZ博文的都知道,LZ最不喜欢elseif,所以策略模式也是有缺点的,就是当策略改变时,我们需要使用elseif去判断到底使用哪一个策略,哪怕使用简单工厂,也避免不了这一点。比如我们又添加一类会员,那么你需要去添加elseif。再比如我们的会员现在打九折了,那么你需要添加一个九折的策略,这没问题,我们对扩展开放,但是你需要修改elseif的分支,将会员的策略从八折替换为九折,这是简单工厂的诟病,在之前已经提到过,对修改开放。

转载于:https://www.cnblogs.com/2019lgg/p/11084065.html

七:策略模式(不同等级会员打折算法)相关推荐

  1. java 策略模式会员_七:策略模式(不同等级会员打折算法)

    定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化: 下面给出策略模式的类图,引自百度百科. 策略模式在LZ第一次接触到的时 ...

  2. 打折算法 Java_JAVA算法策略模式之商品打折 满x送x

    场景:某超市收银台,营业员根据客户购买的商品和数量向客户收费. 问题:超市某段时间会有打折活动(例如打8折),满XXX元送XXX元活动,满XXX元送XXX积分活动等等. 算法类,可能是打折,满XX送X ...

  3. JAVA算法策略模式之商品打折 满x送x

    场景:某超市收银台,营业员根据客户购买的商品和数量向客户收费. 问题:超市某段时间会有打折活动(例如打8折),满XXX元送XXX元活动,满XXX元送XXX积分活动等等. 算法类,可能是打折,满XX送X ...

  4. 策略模式--实现商场打折

    前言: 上一篇博客中写明了简单工厂的引用,其实这篇博客和上一篇类似,是利用了策略加简单工厂的方法实现的.为了我们的重构可以运用上设计模式,本次运用了客户端的形式展现出来,具体请往下看: 策略模式: 顾 ...

  5. 6.泡妞与设计模式(七)策略模式

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

  6. 算法的封装与切换——策略模式

    本文转载自 :http://blog.csdn.net/lovelion/article/details/7818983 俗话说:条条大路通罗马.在很多情况下,实现某个目标的途径不止一条,例如我们在外 ...

  7. python简单的购物程序代码打折_策略模式----商场促销--Python版

    策略模式 示例: 商场收银软件---营业员根据客户所购买商品的单价和数量,向客户收费. 商场会不定期的举行各种活动,如 满100减30, 满200减70, 打8折, 满100积分10点等. 很容易想到 ...

  8. Java设计模式(七)策略模式 模板模式

    (十三)策略模式 策略图案限定了多个封装算法,该算法可以相互替换包.法的客户.借用还有一位大神的样例. interface ICalculator{public int calculate(Strin ...

  9. 如何管理和维护算法族?只需知道策略模式

    同样是排序算法,你可以选择冒泡排序.选择排序.插入排序.快速排序等等,也即是说,为了实现排序这一个目的,有很多种算法可以选择.这些不同的排序算法构成了一个算法族,你可以在需要的时候,根据需求或者条件限 ...

最新文章

  1. ASP.NET 2.0 的 Event Validation
  2. WinAPI: GetTickCount - 获取系统已启动的时间
  3. Javascript 函数声明和函数表达式的区别
  4. php 表单提交及验证 tp,ThinkPHP表单自动提交验证实例教程
  5. 天津大学计算机学院院长及副院长,李晓红 教授
  6. 牛客假日团队赛5 F 随机数 BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 (dfs记忆化搜索的数位DP)...
  7. 【2018.5.12】模拟赛之三-ssl2415 连通块【并查集】
  8. ds图—最小生成树_Python实现最小生成树
  9. Spark与Pandas中DataFrame的详细对比
  10. python训练聊天机器人词库_[ ChatterBot聊天机器人 ] ChatterBot训练数据以及使用三方语料库训练数据 - pytorch中文网...
  11. 记一次现网k8s中pod连接数据库异常的问题分析及解决实践(tcp_tw_recycle与tcp_tw_reuse内核参数修改)
  12. 谈谈订单号和流水号的关系
  13. 14届数独-真题标准数独-Day 4-20220119
  14. Mac vmvare vmdk文件使用
  15. 2011—2019年软考中级数据库系统工程师历年真题
  16. 【参赛作品31】openGauss和PostgreSQL的源码目录结构对比
  17. ​什么是响应时间测试?
  18. 一进制存在吗?为什么?
  19. LoRaAN终端OTAA入网方式的详细介绍
  20. 【板绘手绘线稿素材资料】从素描到板绘,超全的人物嘴巴画法!

热门文章

  1. 英国w l 是什么码数_英国广播公司的完整形式是什么?
  2. 基于Python的简单验证码识别
  3. 一头扎进springboot学习笔记
  4. c语言奇数阶幻方构造法,奇数阶面幻方的行列式构造法.pdf
  5. sip协议之注册说明
  6. antd switch 没有根据数据更新
  7. 关于adb不识别设备解决方案
  8. 加州伯克利计算机科学录取,【哈鲁2019录取】恭喜哈鲁学员喜提加州伯克利大学计算机科学专业录取!...
  9. Oracle(甲骨文)这个庞然大物至今未倒之谜
  10. matlab黎曼问题roe格式,Godnov_HLLC 解1D黎曼问题的有限体积法,使用Roe格式做近似 Algorithm 数学计算 238万源代码下载- www.pudn.com...