【设计模式】- 装饰器模式

装饰器模式能够实现为对象动态添加装修功能,它能从一个对象的外部来给对象添加功能,所以有非常灵活的扩展性,我们可以在对原来的代码毫无修改的前提下,为对象添加新功能

除此之外,装饰器模式还能够实现对象的动态组合,借此我们可以很灵活地给动态组合的对象,匹配所需要的功能。

什么是装饰器模式?

装饰器模式包括了以下几个角色:接口、具体对象、装饰类、具体装饰类
接口定义了具体对象的一些实现方法;具体对象定义了一些初始化操作;
装饰类则是一个抽象类,主要用来初始化具体对象的一个类;其他的具体装饰类都继承了该抽象类。

一个简单的Demo

  1. 基础装饰接口:
/**
 * 基础装饰接口.
 */
public interface IDecorator {

    /**
     * 装修方法.
     */
    void decorate();
}
  1. 装饰基础类
/**
 * 装饰基础类.
 *
 */
public class Decorator implements IDecorator {

    @Override
    public void decorate() {
        System.out.println("水电铺设、墙面粉刷。。。");
    }
}
  1. 抽象类
/**
 * 抽象类.
 *
 */
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();
        }
    }
}
  1. 具体装饰类
/**
 * 窗帘装饰类.
 *
 */
public class CurtainDecorator extends BaseDecorator {

    public CurtainDecorator(IDecorator decorator) {
        super(decorator);
    }

    @Override
    public void decorate() {
        System.out.println("窗帘装饰。。。");
        super.decorate();
    }
}
  1. 测试
    public static void main(String[] args) {
        Decorator decorator = new Decorator();

        CurtainDecorator curtainDecorator = new CurtainDecorator(decorator);
        curtainDecorator.decorate();
    }

执行结果:

窗帘装饰。。。
水电铺设、墙面粉刷。。。

优化电商系统中的商品价格策略

由于篇幅原因,只展示部分核心代码。

  1. 计算支付金额接口类
/**
 * 计算支付金额接口类.
 *
 * @author liusj
 * @date 2021/8/23
 */
public interface IBaseCount {

    /**
     * 商品支付金额.
     *
     * @param orderDetail
     * @return
     */
    BigDecimal countPayMoney(OrderDetail orderDetail);
}
  1. 支付基础实现类
/**
 * 支付基础实现类.
 *
 * @author liusj
 * @date 2021/8/23
 */
public class BaseCount implements IBaseCount {

    @Override
    public BigDecimal  countPayMoney(OrderDetail orderDetail) {
        orderDetail.setPayMoney(orderDetail.getMerchandise().getPrice());
        System.out.println("商品元单价金额为:" + orderDetail.getPayMoney());
        return orderDetail.getPayMoney();
    }
}
  1. 计算支付金额的抽象类(装饰类)
/**
 * 计算支付金额的抽象类.
 *
 * @author liusj
 * @date 2021/8/23
 */
@Data
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;
    }
}
  1. 计算使用优惠券后的金额 (具体装饰类)
/**
 * 计算使用优惠券后的金额.
 *
 * @author liusj
 * @date 2021/8/23
 */
public class CouponDecorator extends BaseCountDecorator {

    public CouponDecorator(IBaseCount count) {
        super(count);
    }

    @Override
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
        BigDecimal payTotalMoney = new BigDecimal(0);
        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();
    }
}
  1. 计算使用红包后的金额
/**
 * 计算使用红包后的金额.
 *
 * @author liusj
 * @date 2021/8/23
 */
public class RedPacketDecorator extends BaseCountDecorator {

    public RedPacketDecorator(IBaseCount count) {
        super(count);
    }

    @Override
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
        BigDecimal payTotalMoney = new BigDecimal(0);
        super.countPayMoney(orderDetail);
        payTotalMoney = countReadPacketMoney(orderDetail);
        return payTotalMoney;
    }

    private BigDecimal countReadPacketMoney(OrderDetail orderDetail) {
        BigDecimal redPacket = orderDetail.getMerchandise()
                .getSupportPromotions()
                .get(PromotionType.READ_PACKED)
                .getUserRedPacket()
                .getRedPacket();
        System.out.println("红包优惠金额:" + redPacket);

        orderDetail.setPayMoney(orderDetail.getPayMoney().subtract(redPacket));

        return orderDetail.getPayMoney();
    }
}
  1. 计算促销后的支付价格 (对象的动态组合)
/**
 * 计算促销后的支付价格.
 *
 * @author liusj
 * @date 2021/8/23
 */
public class PromotionFactory {

    public static BigDecimal getPayMoney(OrderDetail orderDetail) {
        // 获取商品设定的促销类型
        Map<PromotionType, SupportPromotions> supportPromotions = orderDetail.getMerchandise().getSupportPromotions();

        // 初始化计算类
        IBaseCount baseCount = new BaseCount();
        // 遍历设置的促销类型,通过装饰器组合促销类型
        if (supportPromotions != null && supportPromotions.size() > 0) {
            for (PromotionType promotionType : supportPromotions.keySet()) {
                baseCount = promotion(supportPromotions.get(promotionType), baseCount);
            }
        }
        return baseCount.countPayMoney(orderDetail);
    }

    /**
     * 组合促销类型.
     *
     * @param supportPromotions
     * @param baseCount
     * @return
     */
    private static IBaseCount promotion(SupportPromotions supportPromotions, IBaseCount baseCount) {
        if (supportPromotions.getPromotionType() == PromotionType.COUPON) {
            baseCount = new CouponDecorator(baseCount);
        } else if (supportPromotions.getPromotionType() == PromotionType.READ_PACKED) {
            baseCount = new RedPacketDecorator(baseCount);
        }
        return baseCount;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章