ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

精通装饰器模式:实现灵活商品定价策略的最佳实践

精通装饰器模式:实现灵活商品定价策略的最佳实践 目录一、装饰器模式的概念及怎么用一基本概念和功能二结构图分析三举例分析二、装饰器模式的基本用法一接口定义去定义具体需要实现的相关方法二具体对象针对需要实现的方法做初始化操作即基本的实现三装饰类抽象类初始化具体对象四其他具体装饰类实现自己特性的需求五实际使用三、具体案例分析目标用装饰器模式动手实现一套商品价格策略的优化方案。1.先建立订单和商品的属性类:主订单详细订单商品促销类型优惠券红包2.建立计算支付金额的接口类以及基本类3.建立计算支付金额的抽象类调用基本类4.优惠券计算类通过继承抽象类来实现所需要的修饰类5.红包计算类通过继承抽象类来实现所需要的修饰类6.通过一个工厂类来组合商品的促销类型7.实际使用操作四、总结参考书籍、文献和资料干货分享感谢您的阅读在现代软件开发中设计模式为我们提供了解决复杂问题的通用框架装饰器模式作为其中的经典之一因其灵活性和扩展性而被广泛应用。然而装饰器模式不仅仅局限于代码结构的优化它还能在实际业务中发挥巨大的作用。本文将带您深入了解装饰器模式的核心概念与应用方法特别是如何利用这一模式在商品定价策略中实现灵活的优化与调整。通过一个实际案例我们将探索如何借助装饰器模式在面对多变的市场需求时快速应对并优化商品的定价策略。这不仅是对设计模式的一个学习更是一次关于如何在实际业务场景中解决问题的深刻体验。无论您是软件开发人员还是产品经理这篇文章都能为您提供具有实际指导意义的思路和方法助力您在工作中更加高效地应对各种挑战。一、装饰器模式的概念及怎么用一基本概念和功能装饰器模式能够实现从一个对象的外部来给对象添加功能有非常灵活的扩展性可以在对原来的代码毫无修改的前提下为对象添加新功能。除此之外装饰器模式还能够实现对象的动态组合借此我们可以很灵活地给动态组合的对象匹配所需要的功能。二结构图分析Component为统一接口也是装饰类和被装饰类的基本类型。ConcreteComponent为具体实现类也是被装饰类他本身是个具有一些功能的完整的类。Decorator是装饰类实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例并可以通过构造函数初始化。而Decorator本身通常采用默认实现他的存在仅仅是一个声明我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。ConcreteDecorator是具体的装饰产品类每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent从而对其进行装饰。三举例分析假设现在有这样一个需求让你设计一个装修功能用户可以动态选择不同的装修功能来装饰自己的房子。例如水电装修、天花板以及粉刷墙等属于基本功能而设计窗帘装饰窗户、设计吊顶装饰房顶等未必是所有用户都需要的这些功能则需要实现动态添加。还有就是一旦有新的装修功能我们也可以实现动态添加。采用装饰器模式可以很好的解决以上问题。二、装饰器模式的基本用法基于装饰器模式实现的装修功能的代码结构简洁易读业务逻辑也非常清晰并且如果我们需要扩展新的装修功能只需要新增一个继承了抽象装饰类的子类即可。装饰器模式包括了以下几个角色接口、具体对象、装饰类、具体装饰类。接口定义了具体对象的一些实现方法具体对象定义了一些初始化操作比如开头设计装修功能的案例中水电装修、天花板以及粉刷墙等都是初始化操作装饰类则是一个抽象类主要用来初始化具体对象的一个类其它的具体装饰类都继承了该抽象类。一接口定义去定义具体需要实现的相关方法/** * 描述定义一个基本装修接口 * * author yanfengzhang * date 2020-04-19 13:32 */ public interface IDecorator { /** * 装修方法 */ void decorate(); }二具体对象针对需要实现的方法做初始化操作即基本的实现/** * 描述装修基本类 * * author yanfengzhang * date 2020-04-19 13:32 */ public class Decorator implements IDecorator { /** * 基本实现方法 */ Override public void decorate() { System.out.println(水电装修、天花板以及粉刷墙.); } }三装饰类抽象类初始化具体对象/** * 描述基本装饰类 * * author yanfengzhang * date 2020-04-19 13:34 */ public abstract class BaseDecorator implements IDecorator { private IDecorator decorator; public BaseDecorator(IDecorator decorator) { this.decorator decorator; } /** * 调用装饰方法 */ Override public void decorate() { if (decorator ! null) { decorator.decorate(); } } }四其他具体装饰类实现自己特性的需求如果我们想要在基础类上添加新的装修功能只需要基于抽象类 BaseDecorator 去实现继承类通过构造函数调用父类以及重写装修方法实现装修窗帘的功能即可。/** * 描述窗帘装饰类 * * author yanfengzhang * date 2020-04-19 13:35 */ public class CurtainDecorator extends BaseDecorator { public CurtainDecorator(IDecorator decorator) { super(decorator); } /** * 窗帘具体装饰方法 */ Override public void decorate() { System.out.println(窗帘装饰。。。); super.decorate(); } }五实际使用/** * 描述具体使用测试 * * author yanfengzhang * date 2020-04-19 13:36 */ public class Test { public static void main(String[] args) { IDecorator decorator new Decorator(); IDecorator curtainDecorator new CurtainDecorator(decorator); curtainDecorator.decorate(); } }三、具体案例分析每逢双十一为了加大商城的优惠力度开发往往要设计红包 限时折扣或红包 抵扣券等组合来实现多重优惠。而在平时由于某些特殊原因商家还会赠送特殊抵扣券给购买用户而特殊抵扣券 各种优惠又是另一种组合方式。要实现以上这类组合优惠的功能刚刚介绍的装饰器模式就很适合用在这里其相互独立、自由组合以及方便动态扩展功能的特性可以很好地解决这类需求。目标用装饰器模式动手实现一套商品价格策略的优化方案。1.先建立订单和商品的属性类:主订单详细订单商品促销类型优惠券红包订单和商品的属性类只建立了几个关键字段主订单包含若干详细订单详细订单中记录了商品信息商品信息中包含了促销类型信息一个商品可以包含多个促销类型只讨论单个促销和组合促销主订单import java.math.BigDecimal; import java.util.List; /** * 描述主订单 * * author yanfengzhang * date 2020-04-19 14:01 */ Data public class Order { /** * 订单ID */ private int id; /** * 订单号 */ private String orderNo; /** * 总支付金额 */ private BigDecimal totalPayMoney; /** * 详细订单列表 */ private ListOrderDetail list; }详细订单import java.math.BigDecimal; /** * 描述详细订单 * * author yanfengzhang * date 2020-04-19 14:06 */ Data public class OrderDetail { /** * 详细订单ID */ private int id; /** * 主订单ID */ private int orderId; /** * 商品详情 */ private Merchandise merchandise; /** * 支付单价 */ private BigDecimal payMoney; }具体商品import java.math.BigDecimal; import java.util.Map; /** * 描述具体商品 * * author yanfengzhang * date 2020-04-19 14:09 */ Data public class Merchandise { /** * 商品SKU */ private String sku; /** * 商品名称 */ private String name; /** * 商品单价 */ private BigDecimal price; /** * 支持促销类型 */ private MapPromotionType, SupportPromotions supportPromotions; }促销类型/** * 描述促销类型 * * author yanfengzhang * date 2020-04-19 14:16 */ public enum PromotionType { /** * 优惠卷 */ COUPON, /** * 红包 */ REDPACKED; }优惠券import java.math.BigDecimal; /** * 描述优惠券 * * author yanfengzhang * date 2020-04-19 14:13 */ Data public class UserCoupon { /** * 优惠券ID */ private int id; /** * 领取优惠券用户ID */ private int userId; /** * 商品SKU */ private String sku; /** * 优惠金额 */ private BigDecimal coupon; }红包import java.math.BigDecimal; /** * 描述红包 * * author yanfengzhang * date 2020-04-19 14:14 */ Data public class UserRedPacket { /** * 红包ID */ private int id; /** * 领取用户ID */ private int userId; /** * 商品SKU */ private String sku; /** * 领取红包金额 */ private BigDecimal redPacket; }促销类型/** * 描述促销类型 * * author yanfengzhang * date 2020-04-19 14:16 */ Data public class SupportPromotions implements Cloneable { /** * 该商品促销的ID */ private int id; /** * 促销类型 1\优惠券 2\红包 */ private PromotionType promotionType; /** * 优先级 */ private int priority; /** * 用户领取该商品的优惠券 */ private UserCoupon userCoupon; /** * 用户领取该商品的红包 */ private UserRedPacket userRedPacket; /** * 重写clone方法 */ Override public SupportPromotions clone() { SupportPromotions supportPromotions null; try { supportPromotions (SupportPromotions) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return supportPromotions; } }2.建立计算支付金额的接口类以及基本类基本接口定义/** * 描述计算支付金额接口类 * * author yanfengzhang * date 2020-04-19 14:09 */ public interface IBaseCount { /** * 功能描述计算支付金额 * author yanfengzhang * date 2020-04-19 14:40 * param orderDetail * return BigDecimal */ BigDecimal countPayMoney(OrderDetail orderDetail); }基本实现类/** * 描述支付基本类 * * author yanfengzhang * date 2020-04-19 14:41 */ public class BaseCount implements IBaseCount { Override public BigDecimal countPayMoney(OrderDetail orderDetail) { orderDetail.setPayMoney(orderDetail.getMerchandise().getPrice()); System.out.println(商品原单价金额为 orderDetail.getPayMoney()); return orderDetail.getPayMoney(); } }3.建立计算支付金额的抽象类调用基本类/** * 描述计算支付金额的抽象类 * * author yanfengzhang * date 2020-04-19 14:48 */ public abstract class BaseCountDecorator implements IBaseCount { private IBaseCount count; public BaseCountDecorator(IBaseCount count) { this.count count; } Override public BigDecimal countPayMoney(OrderDetail orderDetail) { BigDecimal payTotalMoney new BigDecimal(0); if (count ! null) { payTotalMoney count.countPayMoney(orderDetail); } return payTotalMoney; } }4.优惠券计算类通过继承抽象类来实现所需要的修饰类/** * 描述计算使用优惠券后的金额 * * author yanfengzhang * date 2020-04-19 14:50 */ public class CouponDecorator extends BaseCountDecorator { public CouponDecorator(IBaseCount count) { super(count); } Override public BigDecimal countPayMoney(OrderDetail orderDetail) { BigDecimal payTotalMoney new BigDecimal(0); payTotalMoney super.countPayMoney(orderDetail); payTotalMoney countCouponPayMoney(orderDetail); return payTotalMoney; } private BigDecimal countCouponPayMoney(OrderDetail orderDetail) { BigDecimal coupon orderDetail.getMerchandise().getSupportPromotions().get(PromotionType.COUPON).getUserCoupon().getCoupon(); System.out.println(优惠券金额 coupon); orderDetail.setPayMoney(orderDetail.getPayMoney().subtract(coupon)); return orderDetail.getPayMoney(); } }5.红包计算类通过继承抽象类来实现所需要的修饰类/** * 描述计算使用红包后的金额 * * author yanfengzhang * date 2020-04-19 15:24 */ public class RedPacketDecorator extends BaseCountDecorator { public RedPacketDecorator(IBaseCount count) { super(count); } Override public BigDecimal countPayMoney(OrderDetail orderDetail) { BigDecimal payTotalMoney new BigDecimal(0); payTotalMoney super.countPayMoney(orderDetail); payTotalMoney countCouponPayMoney(orderDetail); return payTotalMoney; } private BigDecimal countCouponPayMoney(OrderDetail orderDetail) { BigDecimal redPacket orderDetail.getMerchandise().getSupportPromotions().get(PromotionType.REDPACKED).getUserRedPacket().getRedPacket(); System.out.println(红包优惠金额 redPacket); orderDetail.setPayMoney(orderDetail.getPayMoney().subtract(redPacket)); return orderDetail.getPayMoney(); } }6.通过一个工厂类来组合商品的促销类型/** * 描述计算促销后的支付价格 * * author yanfengzhang * date 2020-04-19 14:58 */ public class PromotionFactory { public static BigDecimal getPayMoney(OrderDetail orderDetail) { /**获取给商品设定的促销类型*/ MapPromotionType, SupportPromotions supportPromotionsList orderDetail.getMerchandise().getSupportPromotions(); /**初始化计算类*/ IBaseCount baseCount new BaseCount(); if (supportPromotionsList ! null supportPromotionsList.size() 0) { for (PromotionType promotionType : supportPromotionsList.keySet()) { /**遍历设置的促销类型通过装饰器组合促销类型*/ baseCount protmotion(supportPromotionsList.get(promotionType), baseCount); } } return baseCount.countPayMoney(orderDetail); } /** * 组合促销类型 * param supportPromotions * param baseCount * return */ private static IBaseCount protmotion(SupportPromotions supportPromotions, IBaseCount baseCount) { if (supportPromotions.getPromotionType() PromotionType.COUPON) { baseCount new CouponDecorator(baseCount); } else if (supportPromotions.getPromotionType() PromotionType.REDPACKED) { baseCount new RedPacketDecorator(baseCount); } return baseCount; } }7.实际使用操作/** * 描述测试 * * author yanfengzhang * date 2020-04-19 15:35 */ public class Test { volatile int counter 0; private static Order init(Order order) { MapPromotionType, SupportPromotions supportPromotionslist new HashMapPromotionType, SupportPromotions(); SupportPromotions supportPromotions new SupportPromotions(); supportPromotions.setPromotionType(PromotionType.COUPON); supportPromotions.setPriority(1); UserCoupon userCoupon new UserCoupon(); userCoupon.setCoupon(new BigDecimal(3)); userCoupon.setSku(aaa1111); userCoupon.setUserId(11); supportPromotions.setUserCoupon(userCoupon); supportPromotionslist.put(PromotionType.COUPON, supportPromotions); SupportPromotions supportPromotions1 supportPromotions.clone(); supportPromotions1.setPromotionType(PromotionType.REDPACKED); supportPromotions1.setPriority(2); UserRedPacket userRedPacket new UserRedPacket(); userRedPacket.setId(1); userRedPacket.setRedPacket(new BigDecimal(10)); userRedPacket.setSku(aaa1111); userCoupon.setUserId(11); supportPromotions1.setUserRedPacket(userRedPacket); supportPromotionslist.put(PromotionType.REDPACKED, supportPromotions1); Merchandise merchandise new Merchandise(); merchandise.setSku(aaa1111); merchandise.setName(苹果); merchandise.setPrice(new BigDecimal(20)); merchandise.setSupportPromotions(supportPromotionslist); ListOrderDetail OrderDetailList new ArrayListOrderDetail(); OrderDetail orderDetail new OrderDetail(); orderDetail.setId(1); orderDetail.setOrderId(1111); orderDetail.setMerchandise(merchandise); OrderDetailList.add(orderDetail); order.setList(OrderDetailList); return order; } public static void main(String[] args) throws InterruptedException, IOException { Order order new Order(); init(order); for (OrderDetail orderDetail : order.getList()) { BigDecimal payMoney PromotionFactory.getPayMoney(orderDetail); orderDetail.setPayMoney(payMoney); System.out.println(最终支付金额 orderDetail.getPayMoney()); } } }实际测试输入商品原单价金额为20 红包优惠金额10 优惠券金额3 最终支付金额7四、总结装饰器模式以其灵活性和可扩展性在软件设计中具有不可忽视的价值。通过装饰器模式我们能够在不修改原有代码的情况下为对象动态地添加功能。这种特性特别适合处理那些需要灵活组合和扩展的业务需求。在本篇文章中我们通过对装饰器模式概念和基本用法的讲解结合商品价格策略优化的实际案例展示了如何将这一设计模式应用于现实问题提升系统的可扩展性和维护性。在商品价格策略优化的案例中装饰器模式帮助我们应对复杂的促销组合场景允许多个优惠规则如优惠券、红包等自由组合并灵活应用。这种基于装饰器模式的设计不仅增强了系统的可扩展性也使得促销策略的新增和变更变得更加高效和简便。通过本文的学习您应该能够掌握装饰器模式的核心思想并理解如何将其应用于实际项目中。在未来的开发过程中当面对复杂的需求和不断变化的业务逻辑时装饰器模式将为您提供一个高效的解决方案。希望您能将这一设计模式灵活应用到自己的项目中提升代码质量并帮助团队更好地应对复杂的业务需求。参考书籍、文献和资料1.极客时间课程《Java性能调优实战》刘超2019.2.https://www.cnblogs.com/jzb-blog/p/6717349.html
返回列表