商场促销--策略模式

1.1 商场收银软件

package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){totalPrices = price * num;total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 	数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();		System.out.println("**********************************************");}
}

1.2 增加打折

1.正常收费 2.打八折 3.打七折
package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折):");	discount = Integer.parseInt(sc.nextLine());System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){switch(discount){case 1:totalPrices = price * num;break;case 2:totalPrices = price * num * 0.8;break;case 3:totalPrices = price * num * 0.7;break;}total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();		System.out.println("**********************************************");}
}

1.3 简单工厂实现

商场的活动加大,需要有满300返回100的促销算法,又增加是700就要返200呢?或者说需要现在打三折,又要满300送80呢?

收费抽象类

package com.lhx.design.pattern.test;
//收费抽象类
public abstract class CashSuper {//收取费用的抽象方法,参数为单价和数量public abstract double acceptCash(double price,int num);}
package com.lhx.design.pattern.test;public class CashNormal extends CashSuper {//正常收费,原价返回public double acceptCash(double price,int num){return price * num;}}
package com.lhx.design.pattern.test;public class CashRebate extends CashSuper {private double moneyRebate = 1d;//打折收费。初始化时必需输入折扣率。八折就输入0.8public CashRebate(double moneyRebate){this.moneyRebate = moneyRebate;}//计算收费时需要在原价基础上乘以折扣率public double acceptCash(double price,int num){return price * num * this.moneyRebate;}}
package com.lhx.design.pattern.test;public class CashReturn extends CashSuper {private double moneyCondition = 0d; //返利条件private double moneyReturn = 0d;    //返利值//返利收费。初始化时需要输入返利条件和返利值。//比如“满300返100”,就是moneyCondition=300,moneyReturn=100public CashReturn(double moneyCondition,double moneyReturn){this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//计算收费时,当达到返利条件,就原价减去返利值public double acceptCash(double price,int num){double result = price * num;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return result;}}
package com.lhx.design.pattern.test;public class CashFactory {//收费工厂public static CashSuper createCashAccept(int cashType){CashSuper cs = null;switch (cashType) {case 1:cs = new CashNormal();      //正常收费break;case 2:cs = new CashRebate(0.8d);  //打八折break;case 3:cs = new CashRebate(0.7d);  //打七折break;case 4:cs = new CashReturn(300d,100d);//满300返100break;}return cs;}}

package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	discount = Integer.parseInt(sc.nextLine());System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){//简单工厂模式根据discount的数字选择合适的收费类生成实例CashSuper csuper = CashFactory.createCashAccept(discount);//通过多态,可以根据不同收费策略计算得到收费的结果totalPrices = csuper.acceptCash(price,num);total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}

1.4 策略模式

        我要是需要打五折和满500送200的促销活动,只要在现金工厂当中加两个条件,就okl ,准确的来说是收费对象生产工厂才正确,如果我现在需要增加一种商场促销手段,满100积分10点,以后到一定时候可以领取奖品如何做?

        "有了工厂,何难?加一个积分算法,构造方法有两个参数:条件和返点,让它继承CashSuper,再到现金工厂,哦,不对,是收费对象生成工厂里增加满100积分10点的分支条件,再到界面稍加改动,就行了。"

        简单工厂模式虽然也能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂,以致代码需重新编译部署,这真的是很糟糕的处理方式,所以用它不是最好的办法。面对算法的时常变动,应该有更好的办法。好好去研究一下其他的设计模式,你会找到答案的。

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

Strategy类,定义所有支持的算法的公共接口:

Context类,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。

客户端代码:

1.5 策略模式实现

package com.lhx.design.pattern.test;public class CashContext {private CashSuper cs;   //声明一个CashSuper对象//通过构造方法,传入具体的收费策略public CashContext(CashSuper csuper){this.cs = csuper;}public double getResult(double price,int num){//根据收费策略的不同,获得计算结果return this.cs.acceptCash(price,num);}    
}
package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	discount = Integer.parseInt(sc.nextLine());System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){CashContext cc = null;//根据用户输入,将对应的策略对象作为参数传入CashContent对象中switch(discount){case 1:cc = new CashContext(new CashNormal());break;case 2:cc = new CashContext(new CashRebate(0.8d));break;case 3:cc = new CashContext(new CashRebate(0.7d));break;case 4:cc = new CashContext(new CashReturn(300d,100d));break;}//通过Context的getResult方法的调用,可以得到收取费用的结果//让具体算法与客户进行了隔离totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}

把这个判断过程从客户端程序移走

1.6 策略与简单工厂结合

package com.lhx.design.pattern.test;public class CashContext {private CashSuper cs;   //声明一个CashSuper对象//通过构造方法,传入具体的收费策略public CashContext(int cashType){switch(cashType){case 1:this.cs = new CashNormal();break;case 2:this.cs = new CashRebate(0.8d);break;case 3:this.cs = new CashRebate(0.7d);break;case 4:this.cs = new CashReturn(300d,100d);break;}}public double getResult(double price,int num){//根据收费策略的不同,获得计算结果return this.cs.acceptCash(price,num);}    
}
package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	discount = Integer.parseInt(sc.nextLine());System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){//根据用户输入,将对应的策略对象作为参数传入CashContext对象中CashContext cc = new CashContext(discount);//通过Context的getResult方法的调用,可以得到收取费用的结果//让具体算法与客户进行了隔离totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}

简单工厂模式我需要客户端认识两个类,CashSuper和CashFacory,而策略模式与简单工厂结合的用法,客户端就只需要认识一个类CashContext就可以了。耦合更加降低。

说得没错,我们在客户端实例化的是CashContext的对象,调用的是CashContext的方GetResult,这使得具体的收费算法彻底地与客户端分离。连算法的父类CashSuper都不让客户端认识了。

1.7 策略模式解析

策略模式封装了变化。还有什么不足吗?

因为在CashContext里还是用到了switch,也就是说,如果我们需要增加一种算法,比如'满200送50',你就必须要更改CashContext中的switch代码,这总还是让人很不爽呀。那你说怎么办,有需求就得改呀,任何需求的变更都是需要成本的,但是成本的高低还是有差异的。高手和菜鸟的区别就是高手可以花同样的代价获得最大的收益或者说做同样的事花最小的代价。面对同样的需求,然是改动越小越好。""你的意思是说,还有更好的办法?""当然。这个办法就是用到了反射Reflect)技术,不过今天就不讲了,以后会再提它的。""反射真有这么神奇?"小菜疑惑地望向了远方。
注:在抽象工厂模式章节有对反射的讲解。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/587505.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Folder Icons for Mac v1.8 激活版文件夹个性化图标修改软件

Folder Icons for Mac是一款Mac OS平台上的文件夹图标修改软件,同时也是一款非常有意思的系统美化软件。这款软件的主要功能是可以将Mac的默认文件夹图标更改为非常漂亮有趣的个性化图标。 软件下载:Folder Icons for Mac v1.8 激活版 以下是这款软件的一…

XAMPP本地开发环境软件的最佳替代品

在开发新网站或应用时,选择合适的本地开发环境是至关重要的。本地开发环境让您可以在自己的电脑上搭建和测试网站或应用,直到它们准备好被迁移到线上服务器。一些工具甚至提供了推送到生产环境的功能,以及设置多个本地站点的能力。 XAMPP是一…

Git指令速查

一、Git初始化 作用:初始化git仓库,想要使用git对某个项目进行管理,需要git init进行初始化 # 在当前目录新建一个Git代码库,初始化仓库。 在当前目录下生成一个隐藏文件夹.git,不能修改.git下的任何东西 $ git ini…

【路径规划论文整理(1)】Path Deformation Roadmaps(附带对PRM改进算法、同伦映射的整理)

本系列主要是对精读的一些关于路径搜索论文的整理,包括了论文所拓展的其他一些算法的改进思路。 这是本系列的第一篇文章: Jaillet, Lonard & Simon, Thierry. (2008). Path Deformation Roadmaps: Compact Graphs with Useful Cycles for Motion Pl…

[C++]使用OpenCV去除面积较小的连通域

这是后期补充的部分&#xff0c;和前期的代码不太一样 效果图 源代码 //测试 void CCutImageVS2013Dlg::OnBnClickedTestButton1() {vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point&…

rabbitmq死信交换机,死信队列使用

背景 对于核心业务需要保证消息必须正常消费&#xff0c;就必须考虑消费失败的场景&#xff0c;rabbitmq提供了以下三种消费失败处理机制 直接reject&#xff0c;丢弃消息&#xff08;默认&#xff09;返回nack&#xff0c;消息重新入队列将失败消息投递到指定的交换机 对于核…

Jamba: A Hybrid Transformer-Mamba Language Model

Jamba: A Hybrid Transformer-Mamba Language Model 相关链接&#xff1a;arXiv 关键字&#xff1a;hybrid architecture、Transformer、Mamba、mixture-of-experts (MoE)、language model 摘要 我们介绍了Jamba&#xff0c;一种新的基于新颖混合Transformer-Mamba混合专家&am…

DevOps与CI/CD简介

DevOps 是一种软件开发和运维的文化、实践和方法论&#xff0c;旨在通过加强开发团队和运维团队之间的合作和沟通&#xff0c;实现快速、高效、可靠的软件交付和运维。DevOps 是由 Development&#xff08;开发&#xff09;和 Operations&#xff08;运维&#xff09;两个单词组…

Java基础知识总结(第八篇):集合:Collection(List、Set)、Map、Collections 工具类

声明: 1. 本文根据韩顺平老师教学视频自行整理&#xff0c;以便记忆 2. 若有错误不当之处, 请指出 系列文章目录 Java基础知识总结&#xff08;第一篇&#xff09;&#xff1a;基础语法 Java基础知识总结&#xff08;第二篇&#xff09;&#x…

云智慧发布对象关系型数据库CloudPanguDB,打破传统技术壁垒

近日&#xff0c;云智慧推出关系型数据库CloudPanguDB&#xff08;中文名称&#xff1a;盘古数据库&#xff09;&#xff0c;旨在通过高兼容性能和创新技术架构&#xff0c;降低企业项目整体运营成本。 无论是处理海量复杂数据&#xff0c;还是构建清晰有序的数据结构关系&…

普通Java工程可执行JAR两种打包方式探讨

文章目录 一、需求概述二、代码结构三、运行结果四、打包设置1. 一体化可执行包2. 带外部依赖lib的可执行包 五、打包运行1. 源码放送2. 打包执行3. 打包结果 一、需求概述 普通Java工程 docker-show 实现了定时打印docker应用信息&#xff0c;现在需要将其打包成可执行Jar部署…

A New Image Contrast Enhancement Algorithmusing Exposure Fusion Framework

Abstract 弱光图像由于能见度低&#xff0c;不利于人类观察和计算机视觉算法。为了解决这一问题&#xff0c;人们提出了许多图像增强技术&#xff0c;但现有的方法不可避免地会出现对比度增强不足和过度增强的问题。在本文中&#xff0c;我们提出了一种图像对比度增强算法来提…