大话设计模式 第二章 策略模式购物车价格查询
策略模式定义
定义一系列功能 把它们一个个封装起来 并使它们可以相互替换 提供统一的入口访问包装的功能
问题
添加商品和优惠券到购物车后查询价格
思考
要想获取购物车的支付价格 需要经过所有的优惠券优惠后才能得知
因为有不同类型的优惠券 且已有优惠券对象 所以使用策略模式 这里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.0 1.1. 代码 2.2. 存在的问题 二.代码1.1 增加打折 2.1. 代码 2.2. 存在的问题 三.代码2.0 使用简单工厂写打折类和返利类 3.1. 代码 3. ...
- 【设计模式】第二章 代理模式
第二章 代理模式 文章目录 第二章 代理模式 一.简介 一.静态代理 二.动态代理 1.JDK 代理 2.CGLib 代理 三.总结 一.简介 你可能会对这个设计模式感到陌生,但是你对 Spring ...
- 23种设计模式(第二章创建者模式5种)
第二章创建者模式 单例模式 单例模式有 3 个特点: 单例类只有一个实例对象: 该单例对象必须由单例类自行创建: 单例类对外提供一个访问该单例的全局访问点. 单例模式的实现 单例设计模式分类两种: ...
- No2.大话设计模式学习之策略、装饰、代理模式
No2.大话设计模式学习之策略.装饰.代理模式 2.设计模式-part1 2.1.策略模式 描述:策略模式(Strategy Pattern)指同系列算法家族,内部都遵从算法家族的接口及方法规范 原则 ...
- 第 25 章 策略模式
第 25 章 策略模式 1.编写鸭子项目 编写鸭子项目,具体要求如下: 有各种鸭子(比如野鸭.北京鸭.水鸭等, 鸭子有各种行为,比如叫.飞行等) 显示鸭子的信息 2.传统方案解决鸭子问题 传统方案解决 ...
- 设计模式 ( 十八 ) 策略模式Strategy(对象行为型)
设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕 ...
- 设计模式入门(策略模式)
[0]README 0.1)本文部分文字描述转自 "head first 设计模式",旨在学习 设计模式入门(策略模式) 的基础知识: 0.2)本文章节4和5的source cod ...
- java第二章测试题_MOOC选修课答案第二章单元测试答案_Java程序设计查询答案
MOOC选修课答案第二章单元测试答案_Java程序设计查询答案 更多相关问题 ()是目前规模最大的历史性汉语语文词典.A.<康熙字典>B.<汉语大词典>C.<中华大字典& ...
- 大话设计模式1 简单工厂模式 策略模式
终于得空,本来想看看android的源码,但是想起以前看源码时总有点晕,不清楚为什么要这样设计代码结构,所以决定先把设计模式的相关知识学习一下. 买了n久的大话设计模式啊..终于下定决心开始啃了... ...
最新文章
- javaScript tips —— z-index 对事件机制的影响
- mybaits一:初步认识mybatis
- Highcharts 中文参考文档
- 栈和队列之设计一个有getMin(得到最小值)功能的栈
- jooq 配置oracle_jOOQ配置
- [react] React中怎么检验props?
- python 绘图 hist bin参数_Python-hist,distplot bin宽度不一致问题的解决方案
- C# | C#中变量(局部变量)的声明和范围
- 使用猫狗大战数据集进行一次完整的TensorFlow训练
- 单片机蜂鸣器奏乐代码例子
- web前端优化一些看法
- Java对上传的图片进行格式校验以及安全性校验
- 如何使用爬虫采集搜狐汽车新车资讯
- 使用母版页实现页面布局
- 【LaTex】 - 对齐符号的用法,换行符\\的用法,Misplaced 错误怎么解决
- mysql怎么禁用安全模式_mysql开启和关闭安全模式
- 将一根木棍分成三段,求这三段构成三角形的概率 和 在一圆周上任意取三个点构成锐角三角形的概率是多少
- C++面试常见题目问与答(汇总一)
- 3dmax学习8——曲面修改器
- java:java8新特性(Lambda 表达式、方法引用、构造器引用、数组引用、Stream API)
热门文章
- 如何用python打印一段文字,如何在PYTHON中正确打印阿拉伯文字
- 【小技巧】PDF 转 图片 虚拟打印
- 【饭谈】面试官:速斩此子,切不可引狼入室
- Android版疯狂填字第三关,iOS/安卓版《疯狂填字》答案攻略第三十八关
- Android12之OpenSL ES中Realize实例化AudioManager(十二)
- 光线追踪 — 光照模型
- ASP.NET Core 认证与授权[3]:OAuth OpenID Connect认证
- tcl/tk参考——tcl内建命令
- 电商类目表创建类目树
- 小米总监说软件测试分为这及类