当前位置: 首页 > news >正文

设计模式—策略模式

与其明天开始,不如现在行动!

文章目录

  • 策略模式—商场促销
  • 💎总结


策略模式—商场促销

策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。

现在有一个商场需要一个收银系统,根据客户所买商品的单价和数量来收费。商场总共有三种销售模式:

  1. 第一种是全部商品原价收费
  2. 第二种是全部打八折处理
  3. 第三种是满300返利100

此时可以根据简单工厂模式,收银员只需要输入当前销售模式,让程序自己判断使用哪种计算方式。

抽象收费类:

public abstract class CashSuper {public abstract double acceptCash(double price, int num);
}

正常收费类:

public class CashNormal extends CashSuper{@Overridepublic double acceptCash(double price, int num) {return price * num;}
}

打折收费类:

public class CashRebate extends CashSuper{private double moneyRebate = 1;//初始化时候要输入打折率public CashRebate(double moneyRebate) {this.moneyRebate = moneyRebate;}@Overridepublic double acceptCash(double price, int num) {return price * moneyRebate * num;}
}

返利收费类:

public class CashReturn extends CashSuper{//返利条件private double moneyCondition = 0;//返利值private double moneyReturn = 0;public CashReturn(double moneyCondition, double moneyReturn) {this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}@Overridepublic double acceptCash(double price, int num) {double res = price * num;if (moneyCondition > 0 && res >= moneyCondition) {res = res - Math.floor(res / moneyCondition) * moneyReturn;}return res;}
}

收费对象生成工厂:

public class CashFactory {public static CashSuper createCashAccept(int cashType) {CashSuper cashSuper = null;switch (cashType) {case 1:  //正常收费cashSuper = new CashNormal();break;case 2:  //打八折收费cashSuper = new CashRebate(0.8);break;case 3:  //满300返利100cashSuper = new CashReturn(300, 100);break;}return cashSuper;}
}

界面逻辑:

public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入当前销售模式:1:无促销,2:打折,3:返利");int cashType = Integer.parseInt(sc.nextLine()); //商品销售模式System.out.println("请输入当前商品单价:");double price = Double.parseDouble(sc.nextLine()); //商品单价System.out.println("请输入当前商品数量:");int num = Integer.parseInt(sc.nextLine()); //商品数量double totalPrice = 0; //当前商品价格CashSuper cashSuper = CashFactory.createCashAccept(cashType);totalPrice = cashSuper.acceptCash(price, num);System.out.println("商品总价为:" + totalPrice + "元");}
}

当前程序结构图:

image-20231215195127230

虽然此时我们解决了对象的创建问题,但是商场是一个经常性更改折扣额度和返利额度的地方,如果每次都要重新编译部署,这种方式实在是太繁琐了,所以简单工厂不是最好的,这个时候就应该使用策略模式,让这些促销方式封装起来,让他们之间可以相互替换。

改造简单工厂为策略模式,首先把工厂类删除,改造后的程序:

新增收费上下文类:

public class CashContext {private CashSuper cashSuper;public CashContext(int  cashType) {switch (cashType) {case 1:  //正常收费cashSuper = new CashNormal();break;case 2:  //打八折收费cashSuper = new CashRebate(0.8);break;case 3:  //满300返利100cashSuper = new CashReturn(300, 100);break;}}public double getResult(double price, int num) {return cashSuper.acceptCash(price, num);}
}

界面逻辑改造:

public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入当前销售模式:1:无促销,2:打八折,3:满300返100");int cashType = Integer.parseInt(sc.nextLine()); //商品销售模式System.out.println("请输入当前商品单价:");double price = Double.parseDouble(sc.nextLine()); //商品单价System.out.println("请输入当前商品数量:");int num = Integer.parseInt(sc.nextLine()); //商品数量double totalPrice = 0; //当前商品价格totalPrice = new CashContext(cashType).getResult(price, num);System.out.println("商品总价为:" + totalPrice + "元");}
}

当前程序结构图:

image-20231215203555097

简单工厂模式:我需要让界面也就是客户端,认识两个类:CashSuper和CashFactory

策略模式与简单工厂结合:客户端只需要认识一个类:CashContext

总结:

策略模式是定义一系列算法的方法,从用途上,他们完成的是相同的工作,只是具体的实现有所不同,优点:

  1. 策略模式可以用相同的方式调用所有的算法,减少了各类算法类与使用算法类的耦合。
  2. 而且策略模式可以对每个算法类进行单独的测试,同时修改任何一个算法类也不影响其它算法类。

总的来说,策略模式封装了变化,只要在分析过程中需要再不同的时间或者场景下用不同的规则,此时就可以考虑用策略模式实现的可能性。


💎总结

本文中若是有出现的错误请在评论区或者私信指出,我再进行改正优化,如果文章对你有所帮助,请给博主一个宝贵的三连,感谢大家😘!!!


相关文章:

  • 张正友相机标定法原理与实现
  • 如何将xlsx中的数据通过datagrep导入到mysql数据库表中
  • Spring概述
  • 使用Go实现一个百行聊天服务器
  • leetcode
  • v-md-editor高级使用之自定义目录
  • SpringBoot 3.0 升级之 Swagger 升级
  • 鸿蒙小车之多任务调度实验
  • jetpack compose 学习(2)
  • Linux操作系统:开源的计算机革命
  • Ray RLlib User Guides:模型,处理器和动作分布
  • Java之方法引用
  • MySQL事务与MVCC详解
  • LeetCode Hot100 25.K个一组翻转链表
  • AI日报:麻省理工学院专家呼吁扩大人工智能治理和监管
  • 【Linux系统编程】快速查找errno错误码信息
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Github访问慢解决办法
  • JS函数式编程 数组部分风格 ES6版
  • LeetCode29.两数相除 JavaScript
  • PHP 小技巧
  • Puppeteer:浏览器控制器
  • React Transition Group -- Transition 组件
  • spring cloud gateway 源码解析(4)跨域问题处理
  • Spring-boot 启动时碰到的错误
  • SQLServer之创建数据库快照
  • Zepto.js源码学习之二
  • 从输入URL到页面加载发生了什么
  • 关于List、List?、ListObject的区别
  • 你真的知道 == 和 equals 的区别吗?
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 优秀架构师必须掌握的架构思维
  • ionic入门之数据绑定显示-1
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (LeetCode 49)Anagrams
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (五)MySQL的备份及恢复
  • (一)UDP基本编程步骤
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)JAVA中的堆栈
  • (转载)深入super,看Python如何解决钻石继承难题
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET Core 中插件式开发实现
  • .Net Web项目创建比较不错的参考文章
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • [Android Pro] AndroidX重构和映射