做者:小傅哥
博客:https://bugstack.cn - 原创系列专题文章
html
沉淀、分享、成长,让本身和他人都能有所收获!😄
文无第一,武无第二
java
不一样方向但一样努力的人,都有自身的价值和亮点,也都是能够互相学习的。不要太过于用本身手里的矛去攻击别人的盾🛡,哪怕一时争辩过了也多半多是你被安放的角色不一样。取别人之强补本身之弱,矛与盾的结合可能就是坦克。程序员
能把复杂的知识讲的简单很重要
算法
在学习的过程当中咱们看过不少资料、视频、文档等,由于如今资料视频都较多因此每每一个知识点会有多种多样的视频形式讲解。除了推广营销之外,确实有不少人的视频讲解很是优秀,例如李永乐老师的短视频课,能够在一个黑板上把那么复杂的知识,讲解的那么容易理解,那么透彻。而咱们学习编程的人也是,不仅是要学会把知识点讲明白,也要写明白。编程
🙉提高本身的眼界交往更多同好
设计模式
有时候圈子很重要,就像上学期间你们都会发现班里有这样一类学生👩🎓不怎么听课,可是就是学习好。那假如让他回家呆着,不能在课堂里呢?相似的圈子还有;图书馆、网吧、车友群、技术群等等,均可以给你带来同类爱好的人所分享出来的技能或者你们一块儿烘托出的氛围帮你成长。微信
bugstack虫洞栈
,回复源码下载
获取(打开获取的连接,找到序号18)工程 | 描述 |
---|---|
itstack-demo-design-20-01 | 使用一坨代码实现业务需求 |
itstack-demo-design-20-02 | 经过设计模式优化改造代码,产生对比性从而学习 |
策略模式是一种行为模式,也是替代大量ifelse
的利器。它所能帮你解决的是场景,通常是具备同类可替代的行为逻辑算法场景。好比;不一样类型的交易方式(信用卡、支付宝、微信)、生成惟一ID策略(UUID、DB自增、DB+Redis、雪花算法、Leaf算法)等,均可以使用策略模式进行行为包装,供给外部使用。学习
策略模式也有点像三国演义中诸葛亮给刘关张的锦囊;测试
在本案例中咱们模拟在购买商品时候使用的各类类型优惠券(满减、直减、折扣、n元购)优化
这个场景几乎也是你们的一个平常购物省钱渠道,购买商品的时候都但愿找一些优惠券,让购买的商品更加实惠。并且到了大促的时候就会有更多的优惠券须要计算那些商品一块儿购买更加优惠!!!
这样的场景有时候用户用起来仍是蛮爽的,可是最初这样功能的设定以及产品的不断迭代,对于程序员👨💻开发仍是不太容易的。由于这里包括了不少的规则和优惠逻辑,因此咱们模拟其中的一个计算优惠的方式,使用策略模式来实现。
这里咱们先使用最粗暴的方式来实现功能
对于优惠券的设计最初可能很是简单,就是一个金额的抵扣,也没有如今这么多种类型。因此若是没有这样场景的经验话,每每设计上也是很是简单的。但随着产品功能的不断迭代,若是程序最初设计的不具有很好的扩展性,那么日后就会愈来愈混乱。
itstack-demo-design-20-01 └── src └── main └── java └── org.itstack.demo.design └── CouponDiscountService.java
一坨坨
工程的结构很简单,也是最直接的面向过程开发方式。/** * 博客:https://bugstack.cn - 沉淀、分享、成长,让本身和他人都能有所收获! * 公众号:bugstack虫洞栈 * Create by 小傅哥(fustack) @2020 * 优惠券折扣计算接口 * <p> * 优惠券类型; * 1. 直减券 * 2. 满减券 * 3. 折扣券 * 4. n元购 */ public class CouponDiscountService { public double discountAmount(int type, double typeContent, double skuPrice, double typeExt) { // 1. 直减券 if (1 == type) { return skuPrice - typeContent; } // 2. 满减券 if (2 == type) { if (skuPrice < typeExt) return skuPrice; return skuPrice - typeContent; } // 3. 折扣券 if (3 == type) { return skuPrice * typeContent; } // 4. n元购 if (4 == type) { return typeContent; } return 0D; } }
typeExt
类型。这也是方法的很差扩展性问题。if
语句。实际的代码可能要比这个多不少。接下来使用策略模式来进行代码优化,也算是一次很小的重构。
与上面面向流程式的开发这里会使用设计模式,优惠代码结构,加强总体的扩展性。
itstack-demo-design-20-02 └── src └── main └── java └── org.itstack.demo.design ├── event │ └── MJCouponDiscount.java │ └── NYGCouponDiscount.java │ └── ZJCouponDiscount.java │ └── ZKCouponDiscount.java ├── Context.java └── ICouponDiscount.java
策略模式模型结构
ICouponDiscount
)以及四种优惠券类型的实现方式。public interface ICouponDiscount<T> { /** * 优惠券金额计算 * @param couponInfo 券折扣信息;直减、满减、折扣、N元购 * @param skuPrice sku金额 * @return 优惠后金额 */ BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice); }
满减
public class MJCouponDiscount implements ICouponDiscount<Map<String,String>> { /** * 满减计算 * 1. 判断知足x元后-n元,不然不减 * 2. 最低支付金额1元 */ public BigDecimal discountAmount(Map<String,String> couponInfo, BigDecimal skuPrice) { String x = couponInfo.get("x"); String o = couponInfo.get("n"); // 小于商品金额条件的,直接返回商品原价 if (skuPrice.compareTo(new BigDecimal(x)) < 0) return skuPrice; // 减去优惠金额判断 BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(o)); if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE; return discountAmount; } }
直减
public class ZJCouponDiscount implements ICouponDiscount<Double> { /** * 直减计算 * 1. 使用商品价格减去优惠价格 * 2. 最低支付金额1元 */ public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) { BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(couponInfo)); if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE; return discountAmount; } }
折扣
public class ZKCouponDiscount implements ICouponDiscount<Double> { /** * 折扣计算 * 1. 使用商品价格乘以折扣比例,为最后支付金额 * 2. 保留两位小数 * 3. 最低支付金额1元 */ public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) { BigDecimal discountAmount = skuPrice.multiply(new BigDecimal(couponInfo)).setScale(2, BigDecimal.ROUND_HALF_UP); if (discountAmount.compareTo(BigDecimal.ZERO) < 1) return BigDecimal.ONE; return discountAmount; } }
N元购
public class NYGCouponDiscount implements ICouponDiscount<Double> { /** * n元购购买 * 1. 不管原价多少钱都固定金额购买 */ public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) { return new BigDecimal(couponInfo); } }
public class Context<T> { private ICouponDiscount<T> couponDiscount; public Context(ICouponDiscount<T> couponDiscount) { this.couponDiscount = couponDiscount; } public BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice) { return couponDiscount.discountAmount(couponInfo, skuPrice); } }
@Test public void test_zj() { // 直减;100-10,商品100元 Context<Double> context = new Context<Double>(new ZJCouponDiscount()); BigDecimal discountAmount = context.discountAmount(10D, new BigDecimal(100)); logger.info("测试结果:直减优惠后金额 {}", discountAmount); }
测试结果
15:43:22.035 [main] INFO org.itstack.demo.design.test.ApiTest - 测试结果:直减优惠后金额 90 Process finished with exit code 0
@Test public void test_mj() { // 满100减10,商品100元 Context<Map<String,String>> context = new Context<Map<String,String>>(new MJCouponDiscount()); Map<String,String> mapReq = new HashMap<String, String>(); mapReq.put("x","100"); mapReq.put("n","10"); BigDecimal discountAmount = context.discountAmount(mapReq, new BigDecimal(100)); logger.info("测试结果:满减优惠后金额 {}", discountAmount); }
测试结果
15:43:42.695 [main] INFO org.itstack.demo.design.test.ApiTest - 测试结果:满减优惠后金额 90 Process finished with exit code 0
@Test public void test_zk() { // 折扣9折,商品100元 Context<Double> context = new Context<Double>(new ZKCouponDiscount()); BigDecimal discountAmount = context.discountAmount(0.9D, new BigDecimal(100)); logger.info("测试结果:折扣9折后金额 {}", discountAmount); }
测试结果
15:44:05.602 [main] INFO org.itstack.demo.design.test.ApiTest - 测试结果:折扣9折后金额 90.00 Process finished with exit code 0
@Test public void test_nyg() { // n元购;100-10,商品100元 Context<Double> context = new Context<Double>(new NYGCouponDiscount()); BigDecimal discountAmount = context.discountAmount(90D, new BigDecimal(100)); logger.info("测试结果:n元购优惠后金额 {}", discountAmount);
测试结果
15:44:24.700 [main] INFO org.itstack.demo.design.test.ApiTest - 测试结果:n元购优惠后金额 90 Process finished with exit code 0
100元
上折扣10元
,最终支付90元
。策略模式
、适配器模式
、组合模式
等,在一些结构上是比较类似的,可是每个模式是有本身的逻辑特色,在使用的过程当中最佳的方式是通过较多的实践来吸收经验,为后续的研发设计提供更好的技术输出。1. 重学 Java 设计模式:实战工厂方法模式「多种类型商品不一样接口,统一发奖服务搭建场景」
2. 重学 Java 设计模式:实战原型模式「上机考试多套试,每人题目和答案乱序排列场景」
3. 重学 Java 设计模式:实战桥接模式「多支付渠道(微信、支付宝)与多支付模式(刷脸、指纹)场景」
4. 重学 Java 设计模式:实战组合模式「营销差别化人群发券,决策树引擎搭建场景」
5. 重学 Java 设计模式:实战外观模式「基于SpringBoot开发门面模式中间件,统一控制接口白名单场景」
6. 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」
7. 重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程当中,配置文件回滚场景」