设计模式之装饰模式

185 阅读4分钟

装饰模式 HelloWorld


/**
 * 定义一个基本装修接口
 * @author admin
 *
 */
public interface IDecorator {
  
  /**
   * 装修方法
   */
  void decorate();

}

/**
 * 装修基本类
 * @author admin
 *
 */
public class Decorator implements IDecorator{

  /**
   * 基本实现方法
   */
  public void decorate() {
    System.out.println("水电装修、天花板以及粉刷墙。。。");
  }

}

/**
 * 基本装饰类
 * @author admin
 *
 */
public abstract class BaseDecorator implements IDecorator{

  private IDecorator decorator;
  
  public BaseDecorator(IDecorator decorator) {
    this.decorator = decorator;
  }
  
  /**
   * 调用装饰方法
   */
  public void decorate() {
    if(decorator != null) {
      decorator.decorate();
    }
  }
}

/**
 * 窗帘装饰类
 * @author admin
 *
 */
public class CurtainDecorator extends BaseDecorator{

  public CurtainDecorator(IDecorator decorator) {
    super(decorator);
  }
  
  /**
   * 窗帘具体装饰方法
   */
  @Override
  public void decorate() {
    System.out.println("窗帘装饰。。。");
    super.decorate();
  }

}

    public static void main( String[] args )
    {
      IDecorator decorator = new Decorator();
      IDecorator curtainDecorator = new CurtainDecorator(decorator);
      curtainDecorator.decorate();
        
    }

运行结果


窗帘装饰。。。
水电装修、天花板以及粉刷墙。。。

通过这个案例,我们可以了解到:如果我们想要在基础类上添加新的装修功能,只需要基于抽象类 BaseDecorator 去实现继承类,通过构造函数调用父类,以及重写装修方法实现装修窗帘的功能即可。在 main 函数中,我们通过实例化装饰类,调用装修方法,即可在基础装修的前提下,获得窗帘装修功能。基于装饰器模式实现的装修功能的代码结构简洁易读,业务逻辑也非常清晰,并且如果我们需要扩展新的装修功能,只需要新增一个继承了抽象装饰类的子类即可。在这个案例中,我们仅实现了业务扩展功能,接下来,我将通过装饰器模式优化电商系统中的商品价格策略,实现不同促销活动的灵活组合。

装饰模式在电商价格策略中的应用


/**
 * 主订单
 * @author admin
 *
 */
public class Order {
  
  private int id; //订单ID
  private String orderNo; //订单号
  private BigDecimal totalPayMoney; //总支付金额
  private List<OrderDetail> list; //详细订单列表
}

/**
 * 详细订单
 * @author admin
 *
 */
public class OrderDetail {
  private int id; //详细订单ID
  private int orderId;//主订单ID
  private Merchandise merchandise; //商品详情
  private BigDecimal payMoney; //支付单价
}

/**
 * 商品
 * @author admin
 *
 */
public class Merchandise {
  
  private String sku;//商品SKU
  private String name; //商品名称
  private BigDecimal price; //商品单价
  private Map<PromotionType, SupportPromotions> supportPromotions; //支持促销类型
}

/**
 * 促销类型
 * @author admin
 *
 */
public class SupportPromotions implements Cloneable{

  private int id;//该商品促销的ID
  private PromotionType promotionType;//促销类型 1\优惠券 2\红包
  private int priority; //优先级
  private UserCoupon userCoupon; //用户领取该商品的优惠券
  private UserRedPacket userRedPacket; //用户领取该商品的红包
  
  //重写clone方法
    public SupportPromotions clone(){
      SupportPromotions supportPromotions = null;
        try{
          supportPromotions = (SupportPromotions)super.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return supportPromotions;
    }
}

/**
 * 优惠券
 * @author admin
 *
 */
public class UserCoupon {
  
  private int id; //优惠券ID
  private int userId; //领取优惠券用户ID
  private String sku; //商品SKU
  private BigDecimal coupon; //优惠金额
}

/**
 * 红包
 * @author admin
 *
 */
public class UserRedPacket {

  private int id; //红包ID
  private int userId; //领取用户ID
  private String sku; //商品SKU
  private BigDecimal redPacket; //领取红包金额
}

/**
 * 计算支付金额接口类
 * @author admin
 *
 */
public interface IBaseCount {
  
  BigDecimal countPayMoney(OrderDetail orderDetail);

}

/**
 * 支付基本类
 * @author admin
 *
 */
public class BaseCount implements IBaseCount{

  public BigDecimal countPayMoney(OrderDetail orderDetail) {
orderDetail.setPayMoney(orderDetail.getMerchandise().getPrice());
    System.out.println("商品原单价金额为:" +  orderDetail.getPayMoney());
    
    return orderDetail.getPayMoney();
  }

}

/**
 * 计算支付金额的抽象类
 * @author admin
 *
 */
public abstract class BaseCountDecorator implements IBaseCount{
  
  private IBaseCount count;
  
  public BaseCountDecorator(IBaseCount count) {
    this.count = count;
  }

  public BigDecimal countPayMoney(OrderDetail orderDetail) {
    BigDecimal payTotalMoney = new BigDecimal(0);
    if(count!=null) {
      payTotalMoney = count.countPayMoney(orderDetail);
    }
    return payTotalMoney;
  }
}

/**
 * 计算使用优惠券后的金额
 * @author admin
 *
 */
public class CouponDecorator extends BaseCountDecorator{

  public CouponDecorator(IBaseCount count) {
    super(count);
  }
  
  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();
  }
}

/**
 * 计算使用红包后的金额
 * @author admin
 *
 */
public class RedPacketDecorator extends BaseCountDecorator{

  public RedPacketDecorator(IBaseCount count) {
    super(count);
  }
  
  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();
  }
}

/**
 * 计算促销后的支付价格
 * @author admin
 *
 */
public class PromotionFactory {
  
  public static BigDecimal getPayMoney(OrderDetail orderDetail) {
    
    //获取给商品设定的促销类型
    Map<PromotionType, 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;
  }

}


    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());
      }
    }