裝飾器模式能夠實現爲對象動態添加裝修功能,它能從一個對象的外部來給對象添加功能,所以有非常靈活的擴展性,我們可以在對原來的代碼毫無修改的前提下,爲對象添加新功能。
除此之外,裝飾器模式還能夠實現對象的動態組合,藉此我們可以很靈活地給動態組合的對象,匹配所需要的功能。
什麼是裝飾器模式?
裝飾器模式包括了以下幾個角色:接口、具體對象、裝飾類、具體裝飾類
接口定義了具體對象的一些實現方法;具體對象定義了一些初始化操作;
裝飾類則是一個抽象類,主要用來初始化具體對象的一個類;其他的具體裝飾類都繼承了該抽象類。
一個簡單的Demo
- 基礎裝飾接口:
/**
* 基礎裝飾接口.
*/
public interface IDecorator {
/**
* 裝修方法.
*/
void decorate();
}
- 裝飾基礎類
/**
* 裝飾基礎類.
*
*/
public class Decorator implements IDecorator {
@Override
public void decorate() {
System.out.println("水電鋪設、牆面粉刷。。。");
}
}
- 抽象類
/**
* 抽象類.
*
*/
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();
}
}
}
- 具體裝飾類
/**
* 窗簾裝飾類.
*
*/
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) {
Decorator decorator = new Decorator();
CurtainDecorator curtainDecorator = new CurtainDecorator(decorator);
curtainDecorator.decorate();
}
執行結果:
窗簾裝飾。。。
水電鋪設、牆面粉刷。。。
優化電商系統中的商品價格策略
由於篇幅原因,只展示部分核心代碼。
- 計算支付金額接口類
/**
* 計算支付金額接口類.
*
* @author liusj
* @date 2021/8/23
*/
public interface IBaseCount {
/**
* 商品支付金額.
*
* @param orderDetail
* @return
*/
BigDecimal countPayMoney(OrderDetail orderDetail);
}
- 支付基礎實現類
/**
* 支付基礎實現類.
*
* @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();
}
}
- 計算支付金額的抽象類(裝飾類)
/**
* 計算支付金額的抽象類.
*
* @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;
}
}
- 計算使用優惠券後的金額 (具體裝飾類)
/**
* 計算使用優惠券後的金額.
*
* @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();
}
}
- 計算使用紅包後的金額
/**
* 計算使用紅包後的金額.
*
* @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();
}
}
- 計算促銷後的支付價格 (對象的動態組合)
/**
* 計算促銷後的支付價格.
*
* @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;
}
}