文章目录

  • 前言
  • 一、代码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. 这样做的好处


总结

面向对象编程并不是类越多越好,类得划分是为了封装,但分类得基础是抽象,具有相同属性和功能得对象得抽象集合才是类。


在开始编程时,我们

大话设计模式——第二章:商场促销策略模式相关推荐

  1. 大话设计模式笔记(二)——商品促销 策略模式

    第二章商品促销--策略模式 需求:商品价格计算,并增加折扣条件 工厂模式UML图 在工厂模式中,调用端代码会通过折扣工厂类生成折扣对象,折扣对象调用折扣方法.这里关联了两个类,工厂类和抽象折扣类. 策 ...

  2. 2.商场促销 - 策略模式 (大话设计模式Kotlin版)

    编程题:制作商场收银软件 利用编程做一个简易的商场收银系统,营业员根据客户购买的商品的单价与数量,向客户收费. 快速实现 马上想到的解决思路:无非是提供两个输入,分别对应商品单价与数量,然后通过计算得 ...

  3. 大话设计模式 第二章 策略模式购物车价格查询

    策略模式定义 定义一系列功能 把它们一个个封装起来 并使它们可以相互替换 提供统一的入口访问包装的功能 问题 添加商品和优惠券到购物车后查询价格 思考 要想获取购物车的支付价格 需要经过所有的优惠券优 ...

  4. 商场促销——策略模式(设计模式)

    商场收银时,如何促销,用打折还是返利,其实都是一些算法,用工厂来生成算法对象,这没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,就这点变化,而封装变化点是我们面向对象的一种很 ...

  5. 商场促销 --- 策略模式

    一,概念 策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化. 二,策略模式的组成 1)抽象策略角色: 策略类,通常由一个接口或者 ...

  6. 商场促销——策略模式

    策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. "面向对象的编程,并不是类越多越好,类的划分是为了封装, ...

  7. 设计模式随笔系列:鸭子-策略模式(Strategy)[原]

    原文地址为: 设计模式随笔系列:鸭子-策略模式(Strategy)[原] 鸭子-策略模式(Strategy) 前言 万事开头难,最近对这句话体会深刻!这篇文章是这个系列正式开始介绍设计模式的第一篇,所 ...

  8. Java设计模式之行为型:策略模式

    一.背景: 在开发中经常遇到这种情况,实现某个功能有多种算法策略,我们可以根据不同环境或者条件选择不同的算法策略来完成该功能,比如查找.排序等,一种常用方式是硬编码在一个类中,如需要提供多种查找算法, ...

  9. java设计模式中不属于创建型模式_23种设计模式第二篇:java工厂模式定义:工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式...

    23种设计模式第二篇:java工厂模式 定义: 工厂模式是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 工厂模式主要是为创建对象提供过渡接口, ...

最新文章

  1. linux卸载netbeans,如何清除NetBeans中的缓存
  2. shell编程必须要掌握的命令-xargs
  3. 【转】IOS动画的实现,其实很简单
  4. 深入理解Spark 2.1 Core (十四):securityManager 类源码分析
  5. 踩坑之旅:springboot+vue+webpack项目实战(一)
  6. 设计模式--责任链模式(COR)
  7. linux sql语句传参数,Linux/Unixshell参数传递到SQL脚本
  8. 数学分析高等代数考研试题考研真题汇总目录2020-01-10更新
  9. 计算机睡眠与休眠有什么区别,小编教你电脑睡眠和休眠的区别是什么.
  10. 根据手机的分辨率和屏幕尺寸计算手机屏幕的PPI
  11. 达梦体系结构(DM8)_yxy
  12. python在excel中数据画线_python中操作excel数据
  13. PHP 经纬度坐标相关计算方法
  14. 赏完超级蓝血月,再来品味这10个与月亮有关的创业项目
  15. 湖北性能优良戴尔服务器,超高密度的1U机架 戴尔R630服务器评测
  16. 判断对象是否具有属性的 5 种方法
  17. JVM Heap Memory和Native Memory
  18. 1、TCP/IP体系结构
  19. 算法工程师10——opencv
  20. scanf输入字符串遇到空格?

热门文章

  1. R语言如何将不规则的日期数据改为规则的日期数据
  2. Java修炼之凡界篇 筑基期 第01卷 入门 番外3 认识IDE和IDEA
  3. jQuery简单动画实例1--王者荣耀手风琴
  4. 深入浅出:了解前端回流跟重绘
  5. IP组播----组播基础 组播服务模型、组播地址
  6. 高级人工智能之神经网络Artificial Neural Network
  7. 用PyTorch实现MNIST手写数字识别(非常详细)
  8. kotlin 子线程睡3秒_Kotlin中线程和协程之间的区别
  9. Java学习——springboot整合mysql、redis、mongodb
  10. Day902.Memory存储引擎 -MySQL实战