大话设计模式——第二章:商场促销策略模式
文章目录
- 前言
- 一、代码1.0
- 1.1. 代码
- 2.2. 存在的问题
- 二、代码1.1 增加打折
- 2.1. 代码
- 2.2. 存在的问题
- 三、代码2.0 使用简单工厂写打折类和返利类
- 3.1. 代码
- 3.2. 存在的问题
- 四、策略模式 代码3.0
- 4.1. 代码
- 4.2. 存在的问题
- 五、 代码3.1 策略模式与简单工厂模式联合
- 5.1. 代码
- 5.2. 这样做的好处
- 总结
前言
做一个商场收银软件,营业员根据客户所购买商品的单价和数量,向顾客收费。
一、代码1.0
1.1. 代码
public class StrategyMode {public static void main(String[] args) {double total = 0;//实际的price 和count可以做个界面,从框中取值double price = 3;int count = 5;total = price * count;System.out.println("商品合计总价:"+total);}
}
实际可以做一个界面出来,用两个文本框输入单价和数量,一个确定按钮来算出每种商品的费用,用个列表框来记录商品的清单,一个标签来记录总数,一个按钮重新开始。
2.2. 存在的问题
如果要打八折,可以使用total*0.8,但是如果不打折了,需要重新修改一遍代码,或者打五折,都需要重新去修改代码。
二、代码1.1 增加打折
2.1. 代码
public class StrategyMode {public static void main(String[] args) {double total = 0;//实际的price 和count可以做个界面,从框中取值double price = 3;int count = 5;total = getTotal("打五折",price,count);System.out.println("商品合计总价:"+total);}public static double getTotal(String type, double price, int count){double totalPrice = 0;switch (type){case "正常收费":totalPrice = price * count;break;case "打八折":totalPrice = price * count * 0.8;break;case "打五折":totalPrice = price * count * 0.5;break;}return totalPrice;}
}
2.2. 存在的问题
三个switch分支语句除了打折多少以外几乎没什么不同,应该考虑重构一下。
如果增加需求要满300-30,还得修改促销类型代码。
在这里可以使用简单工厂模式,先写一个父类,在继承它实现多个打折和返利的子类,利用多态来解决问题。
而且不用打五折、打八折、满300送30,满500送60都分别写一个类,可以将打折写一个类,返利写一个类。
三、代码2.0 使用简单工厂写打折类和返利类
打折基本上是一样得,只要有个初始化参数就可以了。返利需要两个参数。
面向对象编程并不是类越多越好,类得划分是为了封装,但分类得基础是抽象,具有相同属性和功能得对象得抽象集合才是类。
打八折和打五折只是形式不同,抽象分析出来,所有的打折算法都是一样的,所以打折算法是一个类。
3.1. 代码
//现金收取超类
public abstract class CashSuper {//超类的抽象方法,收取现金,参数为原件,返回为当前价public abstract double acceptCash(double money);
}
//无折扣正常收费类
public class CashNormal extends CashSuper{@Override//正常收费,返回原价public double acceptCash(double money) {return money;}
}
//打折类
public class CashRebate extends CashSuper{private double moneyRebate = 1;public CashRebate(double moneyRebate){this.moneyRebate = moneyRebate;}@Overridepublic double acceptCash(double money) {return money * moneyRebate;}
}
//返利类
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 money) {if (money > moneyCondition){return moneyCondition - moneyReturn;}else {return money;}}
}
//现金收费工厂类
public class CashFactory {public static CashSuper createCashAccept(String type){CashSuper cs = null;switch (type){case "正常收费":cs = new CashNormal();break;case "打八折":cs = new CashRebate(0.8);break;case "满300返100":cs = new CashReturn(300,100);break;}return cs;}
}
客户程序主要部分:
public class StrategyMode {public static void main(String[] args) {CashSuper cs = CashFactory.createCashAccept("打八折");double result = cs.acceptCash(88);System.out.println("最后的金额为:"+result);}
}
3.2. 存在的问题
如果需要打五折或者满500减60,需要在收费对象生成工厂增加两个条件。
如果需要增加另外一种促销方式,比如:满100积分10点,以后积分到一定时候可以领取奖品,需要增加一个积分算法,构造方法有两个参数:条件和返点,让它继承CashSuper,再到收费对象生成工厂增加满100积分10点的分支条件。
这样看起来好像还是有点麻烦,简单工厂模式虽然可以解决这个问题,但这个模式只是解决对象创建问题,而且由于工厂本身包括了所有的收费方式,商场是可能经常更换促销方式,每次维护或者扩展收费方式都要改动这个工厂,以致代码需要重新编译部署。
面对算法经常变动,有更好的办法,那就是策略模式。
四、策略模式 代码3.0
策略模式结构图:
本例 中的结构图:
CashNormal、CashRebate、CashReturn和CashSuper不动,CashFactory暂时不用,新增一个CashContext,然后修改客户端程序。
4.1. 代码
CashContext 类:
public class CashContext {private CashSuper cs;public CashContext(CashSuper cs) {this.cs = cs;}public double getResult(double money){return cs.acceptCash(money);}
}
客户程序主要部分:
public class StrategyMode {public static void main(String[] args) {CashContext cashContext = null;String type = "打八折";switch (type){case "正常收费":cashContext = new CashContext(new CashNormal());break;case "打八折":cashContext = new CashContext(new CashRebate(0.8));break;case "满300返100":cashContext = new CashContext(new CashReturn(300,100));break;}double result = cashContext.getResult(300);System.out.println("最后的金额为:"+result);//240.0}
}
4.2. 存在的问题
策略模式使用上了,但是这个程序还是需要在客户端去判断使用哪一算法,还需要进行改进。
那么如何将这个判断过程从客户端程序移走呢?可以使用工厂模式。
简单工厂模式不一定是一个单独的类,可以和策略模式的Context结合。
五、 代码3.1 策略模式与简单工厂模式联合
5.1. 代码
改造后的CashContext 类:
public class CashContext {private CashSuper cs;//构造函数的参数不是具体的收费策略对象,而是类型public CashContext(String type) {switch (type){case "正常收费":cs = new CashNormal();break;case "打八折":cs = new CashRebate(0.8);break;case "满300返100":cs = new CashReturn(300,100);break;}}public double getResult(double money){return cs.acceptCash(money);}
}
客户程序主要部分:
public class StrategyMode {public static void main(String[] args) {CashContext cashContext = null;String type = "打八折";cashContext = new CashContext(type);double result = cashContext.getResult(200);System.out.println("最后的金额为:"+result);}
}
5.2. 这样做的好处
总结
面向对象编程并不是类越多越好,类得划分是为了封装,但分类得基础是抽象,具有相同属性和功能得对象得抽象集合才是类。
在开始编程时,我们
大话设计模式——第二章:商场促销策略模式相关推荐
- 大话设计模式笔记(二)——商品促销 策略模式
第二章商品促销--策略模式 需求:商品价格计算,并增加折扣条件 工厂模式UML图 在工厂模式中,调用端代码会通过折扣工厂类生成折扣对象,折扣对象调用折扣方法.这里关联了两个类,工厂类和抽象折扣类. 策 ...
- 2.商场促销 - 策略模式 (大话设计模式Kotlin版)
编程题:制作商场收银软件 利用编程做一个简易的商场收银系统,营业员根据客户购买的商品的单价与数量,向客户收费. 快速实现 马上想到的解决思路:无非是提供两个输入,分别对应商品单价与数量,然后通过计算得 ...
- 大话设计模式 第二章 策略模式购物车价格查询
策略模式定义 定义一系列功能 把它们一个个封装起来 并使它们可以相互替换 提供统一的入口访问包装的功能 问题 添加商品和优惠券到购物车后查询价格 思考 要想获取购物车的支付价格 需要经过所有的优惠券优 ...
- 商场促销——策略模式(设计模式)
商场收银时,如何促销,用打折还是返利,其实都是一些算法,用工厂来生成算法对象,这没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,就这点变化,而封装变化点是我们面向对象的一种很 ...
- 商场促销 --- 策略模式
一,概念 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 二,策略模式的组成 1)抽象策略角色: 策略类,通常由一个接口或者 ...
- 商场促销——策略模式
策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. "面向对象的编程,并不是类越多越好,类的划分是为了封装, ...
- 设计模式随笔系列:鸭子-策略模式(Strategy)[原]
原文地址为: 设计模式随笔系列:鸭子-策略模式(Strategy)[原] 鸭子-策略模式(Strategy) 前言 万事开头难,最近对这句话体会深刻!这篇文章是这个系列正式开始介绍设计模式的第一篇,所 ...
- Java设计模式之行为型:策略模式
一.背景: 在开发中经常遇到这种情况,实现某个功能有多种算法策略,我们可以根据不同环境或者条件选择不同的算法策略来完成该功能,比如查找.排序等,一种常用方式是硬编码在一个类中,如需要提供多种查找算法, ...
- java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...
23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...
最新文章
- linux卸载netbeans,如何清除NetBeans中的缓存
- shell编程必须要掌握的命令-xargs
- 【转】IOS动画的实现,其实很简单
- 深入理解Spark 2.1 Core (十四):securityManager 类源码分析
- 踩坑之旅:springboot+vue+webpack项目实战(一)
- 设计模式--责任链模式(COR)
- linux sql语句传参数,Linux/Unixshell参数传递到SQL脚本
- 数学分析高等代数考研试题考研真题汇总目录2020-01-10更新
- 计算机睡眠与休眠有什么区别,小编教你电脑睡眠和休眠的区别是什么.
- 根据手机的分辨率和屏幕尺寸计算手机屏幕的PPI
- 达梦体系结构(DM8)_yxy
- python在excel中数据画线_python中操作excel数据
- PHP 经纬度坐标相关计算方法
- 赏完超级蓝血月,再来品味这10个与月亮有关的创业项目
- 湖北性能优良戴尔服务器,超高密度的1U机架 戴尔R630服务器评测
- 判断对象是否具有属性的 5 种方法
- JVM Heap Memory和Native Memory
- 1、TCP/IP体系结构
- 算法工程师10——opencv
- scanf输入字符串遇到空格?
热门文章
- R语言如何将不规则的日期数据改为规则的日期数据
- Java修炼之凡界篇 筑基期 第01卷 入门 番外3 认识IDE和IDEA
- jQuery简单动画实例1--王者荣耀手风琴
- 深入浅出:了解前端回流跟重绘
- IP组播----组播基础 组播服务模型、组播地址
- 高级人工智能之神经网络Artificial Neural Network
- 用PyTorch实现MNIST手写数字识别(非常详细)
- kotlin 子线程睡3秒_Kotlin中线程和协程之间的区别
- Java学习——springboot整合mysql、redis、mongodb
- Day902.Memory存储引擎 -MySQL实战