策略模式定义

定义一系列功能 把它们一个个封装起来 并使它们可以相互替换 提供统一的入口访问包装的功能

问题

添加商品和优惠券到购物车后查询价格

思考

要想获取购物车的支付价格 需要经过所有的优惠券优惠后才能得知
因为有不同类型的优惠券 且已有优惠券对象 所以使用策略模式 这里context和coupon可以合并
重写优惠券的equals和hashCode 同类型优惠券互斥
优惠券顺序 实现Comparable接口排序

类图

代码

测试类

public class BaseTest {public void assertCondition(boolean condition){if(condition){ConsoleUtil.println("success");}else {ConsoleUtil.println("fail");}Assert.assertTrue(condition);}public void assertCondition(boolean condition,String failMsg){if(condition){ConsoleUtil.println("success");}else {ConsoleUtil.println("fail "+failMsg);}Assert.assertTrue(condition);}
}
@Test
public class ShoppingTest extends BaseTest{public void testCalculatorAmount(){BuyerCart buyerCart = new BuyerCart();Good good = new Good(11, "衣服");buyerCart.addGood(good);buyerCart.addGood(good);Coupon coupon = new ReturnCoupon(10,2);buyerCart.addCoupon(coupon);coupon = new DiscountCoupon(0.5f);buyerCart.addCoupon(coupon);Amount amount = buyerCart.getAmount();ConsoleUtil.println(amount);double checkTotalAmount = 22;double checkPayAmount = 22 * 0.5f;checkPayAmount -= Math.floor(checkPayAmount / 10) * 2;double checkCouponAmount = checkTotalAmount - checkPayAmount;Amount checkAmount = new Amount(checkTotalAmount, checkPayAmount, checkCouponAmount);assertCondition(amount.equals(checkAmount));}
}

商品和金额类

public class Amount {private double totalAmount;private double payAmount;private double couponAmount;public Amount(double totalAmount, double payAmount, double couponAmount) {this.totalAmount = totalAmount;this.payAmount = payAmount;this.couponAmount = couponAmount;}public double getTotalAmount() {return totalAmount;}public double getPayAmount() {return payAmount;}public double getCouponAmount() {return couponAmount;}@Overridepublic String toString() {return "Amount{" +"totalAmount=" + ConvertUtil.toString(totalAmount) +", payAmount=" + ConvertUtil.toString(payAmount) +", couponAmount=" + ConvertUtil.toString(couponAmount) +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Amount amount = (Amount) o;return Double.compare(amount.totalAmount, totalAmount) == 0 && Double.compare(amount.payAmount, payAmount) == 0 && Double.compare(amount.couponAmount, couponAmount) == 0;}@Overridepublic int hashCode() {return Objects.hash(totalAmount, payAmount, couponAmount);}
}
package com.nailsoul.pattern.shopping.bean;public class Good {private double price;private String name;public Good(double price, String name) {this.price = price;this.name = name;}public double getPrice() {return price;}public String getName() {return name;}}

购物车

public class BuyerCart {private Map<String,BuyerCartItem> items = new HashMap<>();private List<Coupon> coupons = new LinkedList<>();public Amount getAmount(){double itemsAmount = getItemsAmount();Amount amount = calculatorAmount(itemsAmount);return amount;}private Amount calculatorAmount(double itemsAmount) {if(coupons.size() == 0){return new Amount(itemsAmount,itemsAmount,0);}Collections.sort(coupons);double payAmount = itemsAmount;CouponContext context = new CouponContext();for (Coupon coupon : coupons) {payAmount = context.changeCoupon(coupon).use(payAmount);}double couponAmount = itemsAmount - payAmount;Amount amount = new Amount(itemsAmount, payAmount, couponAmount);return amount;}private double getItemsAmount() {double amount = 0;for (BuyerCartItem item : items.values()) {amount += item.getAmount();}return amount;}public void addGood(Good good) {BuyerCartItem cartItem = items.get(good.getName());if(cartItem == null){cartItem = new BuyerCartItem(good,0);items.put(good.getName(),cartItem);}cartItem.setQuantity(cartItem.getQuantity()+1);}public void addCoupon(Coupon coupon){if(coupons.contains(coupon)){throw new RuntimeException("不能重复添加相同类型的优惠券");}coupons.add(coupon);}}
public class BuyerCartItem {private Good good;private int quantity;public BuyerCartItem(Good good, int quantity) {this.good = good;this.quantity = quantity;}public double getAmount(){return good.getPrice() * quantity;}public int getQuantity() {return quantity;}public void setQuantity(int quantity) {this.quantity = quantity;}
}

优惠券

public abstract class Coupon implements Comparable<Coupon>{protected String type;public Coupon(){String simpleName = getClass().getSimpleName();String suffix = "Coupon";if(simpleName.endsWith(suffix)){simpleName = simpleName.substring(0,simpleName.length()-suffix.length());}type = simpleName;}public abstract double calculation(double amount);public abstract int getOrder();public abstract String getName();@Overridepublic int compareTo(Coupon o) {return compare(getOrder(),o.getOrder());}private static int compare(int order, int order1) {return Integer.compare(order,order1);}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Coupon coupon = (Coupon) o;return Objects.equals(type, coupon.type);}@Overridepublic int hashCode() {return Objects.hash(type);}
}
public class DiscountCoupon extends Coupon{private float discountRate;public DiscountCoupon(float discountRate) {this.discountRate = discountRate;}@Overridepublic double calculation(double amount) {return amount * discountRate;}@Overridepublic int getOrder() {return 0;}@Overridepublic String getName() {return "打"+ ConvertUtil.toString(discountRate * 10)+"折券";}
}

public class ReturnCoupon extends Coupon{private double conditionAmount;private double returnAmount;public ReturnCoupon(double conditionAmount, double returnAmount) {this.conditionAmount = conditionAmount;this.returnAmount = returnAmount;}@Overridepublic double calculation(double amount) {if(amount >= conditionAmount){amount -= Math.floor(amount / conditionAmount) * returnAmount;}return amount;}@Overridepublic int getOrder() {return 1;}@Overridepublic String getName() {return "满"+ ConvertUtil.toString(conditionAmount)+"减"+ConvertUtil.toString(returnAmount)+"券";}
}
public class CouponContext {private Coupon coupon;public CouponContext(){}public CouponContext(Coupon coupon) {changeCoupon(coupon);}public CouponContext changeCoupon(Coupon coupon) {this.coupon = coupon;return this;}public double use(double amount){double payAmount = coupon.calculation(amount);ConsoleUtil.println("使用"+coupon.getName()+"原价"+ ConvertUtil.toString(amount)+" 支付价"+ConvertUtil.toString(payAmount)+" 优惠"+ConvertUtil.toString(amount-payAmount));return payAmount;}
}

大话设计模式 第二章 策略模式购物车价格查询相关推荐

  1. 大话设计模式——第二章:商场促销策略模式

    文章目录 前言 一.代码1.0 1.1. 代码 2.2. 存在的问题 二.代码1.1 增加打折 2.1. 代码 2.2. 存在的问题 三.代码2.0 使用简单工厂写打折类和返利类 3.1. 代码 3. ...

  2. 【设计模式】第二章 代理模式

    第二章 代理模式 文章目录 第二章 代理模式 一.简介 一.静态代理 二.动态代理 1.JDK 代理 2.CGLib 代理 三.总结 一.简介 你可能会对这个设计模式感到陌生,但是你对 Spring ...

  3. 23种设计模式(第二章创建者模式5种)

    第二章创建者模式 单例模式 单例模式有 3 个特点: 单例类只有一个实例对象: 该单例对象必须由单例类自行创建: 单例类对外提供一个访问该单例的全局访问点. 单例模式的实现 单例设计模式分类两种: ​ ...

  4. No2.大话设计模式学习之策略、装饰、代理模式

    No2.大话设计模式学习之策略.装饰.代理模式 2.设计模式-part1 2.1.策略模式 描述:策略模式(Strategy Pattern)指同系列算法家族,内部都遵从算法家族的接口及方法规范 原则 ...

  5. 第 25 章 策略模式

    第 25 章 策略模式 1.编写鸭子项目 编写鸭子项目,具体要求如下: 有各种鸭子(比如野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如叫.飞行等) 显示鸭子的信息 2.传统方案解决鸭子问题 传统方案解决 ...

  6. 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

    设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...

  7. 设计模式入门(策略模式)

    [0]README 0.1)本文部分文字描述转自 "head first 设计模式",旨在学习 设计模式入门(策略模式) 的基础知识: 0.2)本文章节4和5的source cod ...

  8. java第二章测试题_MOOC选修课答案第二章单元测试答案_Java程序设计查询答案

    MOOC选修课答案第二章单元测试答案_Java程序设计查询答案 更多相关问题 ()是目前规模最大的历史性汉语语文词典.A.<康熙字典>B.<汉语大词典>C.<中华大字典& ...

  9. 大话设计模式1 简单工厂模式 策略模式

    终于得空,本来想看看android的源码,但是想起以前看源码时总有点晕,不清楚为什么要这样设计代码结构,所以决定先把设计模式的相关知识学习一下. 买了n久的大话设计模式啊..终于下定决心开始啃了... ...

最新文章

  1. javaScript tips —— z-index 对事件机制的影响
  2. mybaits一:初步认识mybatis
  3. Highcharts 中文参考文档
  4. 栈和队列之设计一个有getMin(得到最小值)功能的栈
  5. jooq 配置oracle_jOOQ配置
  6. [react] React中怎么检验props?
  7. python 绘图 hist bin参数_Python-hist,distplot bin宽度不一致问题的解决方案
  8. C# | C#中变量(局部变量)的声明和范围
  9. 使用猫狗大战数据集进行一次完整的TensorFlow训练
  10. 单片机蜂鸣器奏乐代码例子
  11. web前端优化一些看法
  12. Java对上传的图片进行格式校验以及安全性校验
  13. 如何使用爬虫采集搜狐汽车新车资讯
  14. 使用母版页实现页面布局
  15. 【LaTex】 - 对齐符号的用法,换行符\\的用法,Misplaced 错误怎么解决
  16. mysql怎么禁用安全模式_mysql开启和关闭安全模式
  17. 将一根木棍分成三段,求这三段构成三角形的概率 和  在一圆周上任意取三个点构成锐角三角形的概率是多少
  18. C++面试常见题目问与答(汇总一)
  19. 3dmax学习8——曲面修改器
  20. java:java8新特性(Lambda 表达式、方法引用、构造器引用、数组引用、Stream API)

热门文章

  1. 如何用python打印一段文字,如何在PYTHON中正确打印阿拉伯文字
  2. 【小技巧】PDF 转 图片 虚拟打印
  3. 【饭谈】面试官:速斩此子,切不可引狼入室
  4. Android版疯狂填字第三关,iOS/安卓版《疯狂填字》答案攻略第三十八关
  5. Android12之OpenSL ES中Realize实例化AudioManager(十二)
  6. 光线追踪 — 光照模型
  7. ASP.NET Core 认证与授权[3]:OAuth OpenID Connect认证
  8. tcl/tk参考——tcl内建命令
  9. 电商类目表创建类目树
  10. 小米总监说软件测试分为这及类