网站做镜像,公司网站如何seo,装潢设计学校,专业微信网站建设公司首选公司哪家好文章目录 一、定义#xff1a;策略模式二、模拟场景#xff1a;策略模式三、违背方案#xff1a;策略模式3.0 引入依赖3.1 工程结构3.2 优惠券折扣计算类3.3 单元测试 四、改善代码#xff1a;策略模式4.1 工程结构4.2 策略模式结构图4.3 优惠券折扣实现4.3.1 定义优惠券接… 文章目录 一、定义策略模式二、模拟场景策略模式三、违背方案策略模式3.0 引入依赖3.1 工程结构3.2 优惠券折扣计算类3.3 单元测试 四、改善代码策略模式4.1 工程结构4.2 策略模式结构图4.3 优惠券折扣实现4.3.1 定义优惠券接口4.3.2 满减优惠券接口实现4.3.3 直减优惠券接口实现4.3.4 折扣优惠券接口实现4.3.5 n元购优惠券接口实现4.3.6 策略控制类 4.4 单元测试4.4.1 直减券测试4.4.2 满减券测试4.4.3 折扣券测试4.4.4 n元购测试 五、总结策略模式 一、定义策略模式 策略模式是具有同类可替代的行为逻辑算法场景。比如 不同类型的交易方式(信用卡、支付宝、微信)。生成唯一 ID 策略( UUID 、DB自增、DBRedis、雪花算法、Leaf算法)等。
二、模拟场景策略模式 模拟在购买商品时使用的各种类型优惠券(满减、直减、折扣、m元)。这个场景几乎也是大家的一个日常购物省钱渠道购买商品的时候都希望找一些优惠券让购买的商品更加实惠。而且到了大促的时候就会有更多的优惠券需要计算那些商品一起购买更加优惠。这样的场景有时候用户用起来还是蛮爽的但是最初这样功能的设定以及产品的不断迭代对于程序员开发还是不容易的。 因为这里包括了很多的规则和优惠逻辑所以我们模拟其中的一个计算优惠的方式使用策略模式来实现。
三、违背方案策略模式 对于优惠券的设计最初可能非常简单就是一个金额的折扣也没有现在这么多种类型。 所以如果没有这样场景的经验往往设计上也是非常简单的。 但随着产品功能的不断迭代如果程序最初设计的不具备很好的扩展性那么往后就会越来越混乱。 3.0 引入依赖
dependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/versionscopetest/scope/dependency!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --dependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.62/version/dependency!-- LOGGING begin --dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdversion1.7.5/version/dependencydependencygroupIdorg.slf4j/groupIdartifactIdjcl-over-slf4j/artifactIdversion1.7.5/version/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.0.9/versionexclusionsexclusionartifactIdslf4j-api/artifactIdgroupIdorg.slf4j/groupId/exclusion/exclusions/dependency
/dependencies3.1 工程结构
design-21.0-1
|——src|——main|--java|--com.lino.design|-CouponDiscountService.java|--test|--com.lino.design.test|-ApiTest.java3.2 优惠券折扣计算类 CouponDiscountService.java package com.lino.design;/*** description: 优惠券折扣计算接口*/
public class CouponDiscountService {/*** 计算优惠券折扣** param type 优惠券类型1-直减券2-满减券3-折扣券4-n元购* param typeContent 折扣价格* param skuPrice 商品价格* param typeExt 满减价格* return 折扣后的价格*/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 语句。
3.3 单元测试 ApiTest.java package com.lino.design.test;import com.lino.design.CouponDiscountService;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** description: 单元测试*/
public class ApiTest {private Logger logger LoggerFactory.getLogger(ApiTest.class);Testpublic void test() {CouponDiscountService couponDiscountService new CouponDiscountService();double result1 couponDiscountService.discountAmount(1, 10D, 100D, 0D);logger.info(测试结果直减优惠后金额{}, result1);double result2 couponDiscountService.discountAmount(2, 10D, 100D, 0D);logger.info(测试结果满减优惠后金额{}, result2);double result3 couponDiscountService.discountAmount(3, 0.9D, 100D, 0D);logger.info(测试结果折扣优惠后金额{}, result3);double result4 couponDiscountService.discountAmount(4, 90D, 100D, 0D);logger.info(测试结果n元购金额{}, result4);}
}测试结果 17:05:07.040 [main] INFO com.lino.design.test.ApiTest - 测试结果直减优惠后金额90.0
17:05:07.049 [main] INFO com.lino.design.test.ApiTest - 测试结果满减优惠后金额90.0
17:05:07.049 [main] INFO com.lino.design.test.ApiTest - 测试结果折扣优惠后金额90.0
17:05:07.049 [main] INFO com.lino.design.test.ApiTest - 测试结果n元购金额90.0四、改善代码策略模式 重构使用策略模式优化代码结构增强整体的扩展性。 4.1 工程结构
design-21.0-2
|——src|——main|--java|--com.lino.design|--impl| |--MJCouponDiscount.java| |--NYGCouponDiscount.java| |--ZJCouponDiscount.java| |--ZKCouponDiscount.java|-Context.java|-ICouponDiscount.java|--test|--com.lino.design.test|-ApiTest.java4.2 策略模式结构图 整体的结构模式并不复杂主要体现的不同类型的优惠券在计算优惠券方式的不同计算策略。这里包括一个接口类(ICouponDiscount)以及四种优惠券类型的实现方式。最后提供了策略模式的上下控制类处理整体的策略服务。
4.3 优惠券折扣实现
4.3.1 定义优惠券接口 ICouponDiscount.java package com.lino.design;import java.math.BigDecimal;/*** description: 优惠券折扣计算接口*/
public interface ICouponDiscountT {/*** 计算优惠券折扣** param couponInfo 优惠券信息泛型* param skuPrice 商品价格* return 优惠券折扣后的价格*/BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice);
}定义了优惠券折扣接口也增加了泛型用于不同类型的接口可以传递不同的类型参数。接口中包括商品金额以及出参返回最终折扣后的金额。
4.3.2 满减优惠券接口实现 MJCouponDiscount.java package com.lino.design.impl;import com.lino.design.ICouponDiscount;
import java.math.BigDecimal;
import java.util.Map;/*** description: 满减券*/
public class MJCouponDiscount implements ICouponDiscountMapString, String {/*** 满减计算* 1.判断满足x元后-n元否则不减* 2.最低 支付金额1元** param couponInfo 优惠券信息泛型* param skuPrice 商品价格* return 优惠后价格*/Overridepublic BigDecimal discountAmount(MapString, String couponInfo, BigDecimal skuPrice) {String x couponInfo.get(x);String n couponInfo.get(n);// 小于商品金额条件的直接返回商品原价if (skuPrice.compareTo(new BigDecimal(x)) 0) {return skuPrice;}// 减去优惠金额判断BigDecimal discountAmount skuPrice.subtract(new BigDecimal(n));if (discountAmount.compareTo(BigDecimal.ZERO) 1) {return BigDecimal.ONE;}return discountAmount;}
}4.3.3 直减优惠券接口实现 ZJCouponDiscount.java package com.lino.design.impl;import com.lino.design.ICouponDiscount;
import java.math.BigDecimal;/*** description: 直减券*/
public class ZJCouponDiscount implements ICouponDiscountDouble {/*** 直减计算* 1.使用商品价格减去优惠价格* 2.最低支付金额1元** param couponInfo 优惠券信息泛型* param skuPrice 商品价格* return 优惠后价格*/Overridepublic BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {BigDecimal discountAmount skuPrice.subtract(new BigDecimal(couponInfo));if (discountAmount.compareTo(BigDecimal.ZERO) 1) {return BigDecimal.ONE;}return discountAmount;}
}4.3.4 折扣优惠券接口实现 ZKCouponDiscount.java package com.lino.design.impl;import com.lino.design.ICouponDiscount;
import java.math.BigDecimal;/*** description: 折扣券*/
public class ZKCouponDiscount implements ICouponDiscountDouble {/*** 折扣计算* 1.使用商品价格乘以折扣比例为最后支付金额* 2.保留两位小数* 3.最低支付金额1元** param couponInfo 优惠券信息泛型* param skuPrice 商品价格* return 优惠后价格*/Overridepublic 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;}
}4.3.5 n元购优惠券接口实现 NYGCouponDiscount.java package com.lino.design.impl;import com.lino.design.ICouponDiscount;
import java.math.BigDecimal;
import java.util.Map;/*** description: n元购*/
public class NYGCouponDiscount implements ICouponDiscountDouble {/*** n元购* 1.无论原价多少钱都固定金额购买** param couponInfo 优惠券信息泛型* param skuPrice 商品价格* return 优惠后价格*/Overridepublic BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {return new BigDecimal(couponInfo);}
}4.3.6 策略控制类 Context.java package com.lino.design;import java.math.BigDecimal;/*** description: 策略控制类*/
public class ContextT {private ICouponDiscountT couponDiscount;public Context(ICouponDiscountT couponDiscount) {this.couponDiscount couponDiscount;}/*** 计算优惠券折扣** param couponInfo 优惠券信息泛型* param skuPrice 商品价格* return 优惠券折扣后的价格*/public BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice) {return couponDiscount.discountAmount(couponInfo, skuPrice);}
}策略模式的控制类主要是外部可以传递不同的策略实现再通过统一的方法执行优惠策略计算。另外这里也可以包装出 map 结构让外部只需要对应的泛型类型即可使用相应的服务。
4.4 单元测试
4.4.1 直减券测试 ApiTest.java Test
public void test_zj() {ContextDouble context new Context(new ZJCouponDiscount());BigDecimal discountAmount context.discountAmount(10D, new BigDecimal(100));logger.info(测试结果直减优惠后金额{}, discountAmount);
}测试结果 17:16:00.390 [main] INFO com.lino.design.test.ApiTest - 测试结果直减优惠后金额904.4.2 满减券测试 ApiTest.java Test
public void test_mj() {ContextMapString, String context new Context(new MJCouponDiscount());MapString, String mapReq new HashMap();mapReq.put(x, 100);mapReq.put(n, 10);BigDecimal discountAmount context.discountAmount(mapReq, new BigDecimal(100));logger.info(测试结果满减优惠后金额{}, discountAmount);
}测试结果 17:16:35.300 [main] INFO com.lino.design.test.ApiTest - 测试结果满减优惠后金额904.4.3 折扣券测试 ApiTest.java Test
public void test_zk() {ContextDouble context new Context(new ZKCouponDiscount());BigDecimal discountAmount context.discountAmount(0.9D, new BigDecimal(100));logger.info(测试结果折扣9折后金额{}, discountAmount);
}测试结果 17:17:06.907 [main] INFO com.lino.design.test.ApiTest - 测试结果折扣9折后金额90.004.4.4 n元购测试 ApiTest.java Test
public void test_nyg() {ContextDouble context new Context(new NYGCouponDiscount());BigDecimal discountAmount context.discountAmount(90D, new BigDecimal(100));logger.info(测试结果n元购优惠后金额{}, discountAmount);
}测试结果 17:17:35.616 [main] INFO com.lino.design.test.ApiTest - 测试结果n元购优惠后金额90以上四个测试分别验证了不同类型优惠券的优惠策略测试结果是满足我们的预期。 这里四种优惠券最终都是再原价 100 元上折扣 10 元最终支付 90 元。 五、总结策略模式
策略模式案例相对来说并不复杂主要的逻辑都是体现在关于不同类型优惠券的计算折扣策略上。 结构相对来说也比较简单在实际的开发中这样的设计模式也是非常常用的。另外策略模式与命令模式、适配器模式结构相似但是思路是有差异的。 通过策略模式的使用可以把我们方法中的 if 语句优化掉大量的 if 语句使用会让代码难为扩展也不好维护同时在后期遇到各种问题也很难维护。在使用策略模式可以很好的满足隔离性和扩展性对于不断新增的需求也非常方便承接。策略模式、适配器模式、组合模式 等在一些结构上是比较相似的。但是每一个模式都有自己的逻辑特点在使用的过程中最佳的方式是经过较多的实践来吸取经验为后续的研发设计提供更好的技术输出。