策略模式在票务系统的使用
为什么要选用策略模式
票务系统为用户分等级,普通用户,白银用户,黄金用户; 每种不同的用户都有不同的折扣策略。
同时,为了系统的开放性,我们设计的项目是可以添加新的用户级别同时不修改源代码。
(资料图片仅供参考)
这些就恰恰是策略模式能解决的问题,这就是为什么我要选它。
不懂策略模式的小伙伴可以看我的介绍: 【设计模式】行为型模式其九: 策略模式 - 掘金 (juejin.cn)
项目中书写
策略抽象类
// 定义打折方法
public interface Discount { BigDecimal discount(BigDecimal price);}复制代码
具体策略类
// 普通用户采取不打折策略
public class NormalDiscount implements Discount{ private final double discount; public NormalDiscount(){ this.discount = 1.0; } @Override public BigDecimal discount(BigDecimal price) { return price.multiply(new BigDecimal(discount)); }}复制代码
// 白银用户采取打八折的方式
public class SilverDiscount implements Discount{ private final double discount; public SilverDiscount(){ this.discount = 0.8; } @Override public BigDecimal discount(BigDecimal price) { return price.multiply(new BigDecimal(discount)); }}复制代码
// 黄金用户采取打六折的方式
public class GoldDiscount implements Discount{ private final double discount; public GoldDiscount(){ this.discount = 0.6; } @Override public BigDecimal discount(BigDecimal price) { return price.multiply(new BigDecimal(discount)); }}复制代码
具体环境类
将打折功能放在一个对象内,公开一个获得价格接口,便于调用和统一处理
public class Price { private BigDecimal price; private Discount discount; public void setPrice(BigDecimal price){ this.price = price; } public void setDiscount(Discount discount){ this.discount = discount; } public BigDecimal getPrice(){ return discount.discount(this.price); }}复制代码
XML 文件
com.example.ticket.service.stratege.SilverDiscount 复制代码
XMl文件读取类
public class DiscountXmlUtil { public static Object getBean(){ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document doc = documentBuilder.parse(\"D:\gitee icket icket-management-system icket\src\main\" + \"\resources\" + \"\discount.xml\"); NodeList className = doc.getElementsByTagName(\"className\"); Node firstChild = className.item(0).getFirstChild(); String nodeValue = firstChild.getNodeValue(); Class>aClass = Class.forName(nodeValue); Constructor>constructor = aClass.getConstructor(); return Class.forName(nodeValue).getConstructor().newInstance(); } catch (ParserConfigurationException | IOException | SAXException | ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) { throw new RuntimeException(e); } }}复制代码
具体调用类
我们这算是一个系统,所以我们何时会去使用价格打折机制呢?
没错,就是生成订单的时候,所以我们调用方法写在service层里。
那我们肯定是要根据前端传来的用户信息,读取用户类的身份字段,并为其选择合适的打折策略。
@Overridepublic SysOrder getOrder() { // 获得价格对象 Price price = new Price(); // 设置商品价格 price.setPrice(new BigDecimal(\"10.00\")); // 设置打折策略, 根据XML文件来设置 price.setDiscount((Discount) DiscountXmlUtil.getBean()); // 通过统一接口来获得价格 BigDecimal price1 = price.getPrice(); // 之后就是对Order对象的封装, 省略。。。。。。 System.out.println(price1); return null;}复制代码
一些细节提示
具体类里的discount字段属于赋值一次,永远不变的,所以加上final字段。 当你想要添加其它打折策略, 可以直接继承Discount,然后改写方法即可 当你还要进行一些特殊操作,比如添加积分,可以在具体打折类进行操作。当然,我更建议在Price对象里进行操作,毕竟这算是一种公共操作,可以在Price里统一进行。 根据XML文件来动态生成策略类,这样虽然不会修改源代码,但是需要根据用户身份来修改XML文件,所以我们还得在DiscountXMLUtil类中书写修改XML文件的方法。原文链接:https://juejin.cn/post/7226013112406294589
关键词: