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

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

策略模式在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的分支,将会员的策略从八折替换为九折,这是简单工厂的诟病,在之前已经提到过,对修改开放。

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

  1. java reactor模式例子_回顾 Reactor 模式

    Reactor 作为网络编程库的核心模式的 Reactor 模式是网络编程中的最常用的模式,反应器 Reactor 又名分派器 Dispatcher, 或通知器 Notifier, 重温一下 POSA ...

  2. JAVA工厂模式优缺点_简单工厂模式、工厂模式和抽象工厂模式区别及优缺点

    各位小伙伴好,今天给大家主要介绍一下简单工厂模式.工厂模式和抽象工厂模式的区别及各自的优缺点. (本文实现语言为Python3) [前言] 众所周知今天所讲的内容是 设计模式的一类:对于设计模式这个概 ...

  3. java 工厂模式优点_抽象工厂模式的优缺点和适用场景

    抽象工厂模式的优点 抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束.所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系 ...

  4. 反模式设计_设计模式:模式或反模式,这就是问题

    反模式设计 我最近遇到了Wiki页面" Anti-pattern" ,其中包含详尽的反模式列表. 其中一些对我来说很明显. 他们中的一些让我想了一下,其他的让我想了更多. 然后,我 ...

  5. 商业模式新生代_免费商业模式——《商业模式新生代》读书笔记之五

    慢慢来,比较快,阿旺的文章是帮您培养长效收益思维的文章,赞同的伙伴关注我! 今天继续讲第四种商业模式---免费商业模式.免费,顾名思义,就是不要钱,但是我们常说,不谈盈利的商业模式都是耍流氓,天下真的 ...

  6. 安卓暗黑模式软件_微信暗黑模式版本下载-微信暗黑版本v7.0.11 安卓版-腾牛安卓网...

    微信暗黑版本是指的全新推出的暗黑模式版本,这不仅仅是夜间模式哦,而是多方协调下,开发的一个全新黑色主题版本.暗黑版下不仅聊天页面和第一层页面入口是黑色的,小程序微信游戏等,也都会全面覆盖. 微信暗黑模 ...

  7. java 工厂模式 计算器_简单工厂模式实现简易计算器

    packageFactoryMethodPattern;/*创建人:czc 创建时间:2019/12/16 创建用途:简单工厂模式实现计算器--主界面*/ import javax.swing.*;i ...

  8. java 横向 打印出来_在双工模式下使用Java打印横向文档

    我有一个JasperReports报告要在双面打印机上以横向模式打印.在此我要支持PCL5和PCL6打印驱动程序. 在互联网上搜索,我发现了以下代码片段来完成这项工作: import java.awt ...

  9. java 责任链模式 链表_责任链模式的实现及源码中应用

    01 - 责任链模式的实现 假设一个出差任务的流程需要审批出差行程和出差报销金额.那么,对应两个部门的审核.我们先定义一个出差任务Task类: 然后,我们定义一个抽象的处理类Handler,其中具体的 ...

最新文章

  1. 网络系统管理之静态路由配置
  2. ML之XGBoost:XGBoost案例应用实战(原生接口实现+Scikit-learn接口实现)
  3. 01背包模板、全然背包 and 多重背包(模板)
  4. 【转】深入了解CPU两大架构ARM与X86
  5. uva10050-罢工
  6. 5g虚拟技术旅游_5G造就文旅新时代,驴迹科技探索智慧出行创新领域
  7. 毕业设计一周一记02
  8. 初学Rman 写的备份脚本
  9. 学习阮一峰老师-互联网协议笔记(IP/UDP/TCP/HTTP)
  10. Windows 11 修改Edge按 Alt+Tab 键为单个窗口
  11. QT 自定义圆形QLabel 加载圆形图片
  12. mysql d是什么意思_是mysqld意思
  13. python大众点评霸王餐_划重点:如何报名大众点评霸王餐?怎么做才能中奖?
  14. 任意四面体的外接球/三维空间不共面四点确定唯一球面(附完整代码)
  15. (5/8 软件漏洞攻击利用技术)如何成为一名黑客(网络安全从业者)——网络攻击技术篇
  16. 什么是嵌入式AI开发?人工智能芯片指什么?STM32、树莓派、Jetson TX2、华为昇腾部署神经网络区别在哪?
  17. Android 实战项目:简单计算器
  18. 鸿蒙内核阅读笔记-定时器
  19. C++核心之类和对象——对象的初始化和清理下P110-P113
  20. Windows下Git使用记录--03 Git GUI与金山快盘组建私人代码仓库进行项目开发

热门文章

  1. 《火星人开发纪实:敏捷开发一千零一夜》序言
  2. rman备份常用命令
  3. BCH粉必转 | 围绕BCH建立的相关项目和应用列表汇总
  4. BCH现阶段面临的一些问题以及可能的解决方向
  5. 比特币大涨,如何辨别牛市是否真正到来?
  6. Java - PriorityQueue
  7. 洛谷——P1098 字符串的展开
  8. 各类商会协会单位类织梦模板(带手机端)
  9. 【转】windows平台多线程同步之Mutex的应用
  10. paip.http 404错误 的解决