跳至主要內容

装饰器模式

Mr.Hope...大约 2 分钟

装饰是一种结构设计模式, 允许你通过将对象放入特殊封装对象中来为原对象增加新的行为。

由于目标对象和装饰器遵循同一接口, 因此你可用装饰来对对象进行无限次的封装。 结果对象将获得所有封装器叠加而来的行为。

使用示例: 装饰在 Java 代码中可谓是标准配置, 尤其是在与流式加载相关的代码中。

Java 核心程序库中有一些关于装饰的示例:

识别方法: 装饰可通过以当前类或对象为参数的创建方法或构造函数来识别。

订单优惠券与会员机制

Order:订单

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
    private Double price;
    private Integer orderId;
    private String orderNo;
    private Double pay;
    private List<String> promotions;//参与的活动

}

decorators

decorators/OrderDecorator.java:定义了装饰方法

/**
 * 订单装饰者接口
 */
public interface OrderDecorator {
    //抽象装饰方法
    Order decorator(Order order);
}

decorators/VipOrderDecorator.java:VIP机制装饰器

/**
 * vip装饰者
 */
// VIP 订单装饰器
public class VipOrderDecorator implements OrderDecorator {
    private final Vip vip;

    public VipOrderDecorator(Vip vip) {
        this.vip = vip;
    }

    @Override
    public Order decorator(Order order) {
        order.setPay(order.getPay() * vip.getDiscount());
        // 活动促销
        String promotions = "VIP享受"+(int)(vip.getDiscount()*10)+"折优惠";
        order.getPromotions().add(promotions);
        return order;
    }
}

decorators/CouponOrderDecorator.java:VIP机制装饰器

/**
 * 优惠券装饰者
 */
// 优惠券订单装饰器
public class CouponOrderDecorator implements OrderDecorator {
    private final Coupon coupon;

    public CouponOrderDecorator(Coupon coupon) {
        this.coupon = coupon;
    }

    @Override
    public Order decorator(Order order) {
        order.setPay(order.getPay() - coupon.getDiscountAmount());
        // 活动促销
        String promotions = "使用" + coupon.getDiscountAmount() + "元优惠券";
        order.getPromotions().add(promotions);
        return order;
    }
}

constants

constants/Vip.java:会员机制的折扣

/**
 * 活动枚举
 */
public enum Vip {
    VIP1(0.9), // 折扣 0.9
    VIP2(0.8), // 折扣 0.8
    VIP3(0.7); // 折扣 0.7

    private final double discount;

    Vip(double discount) {
        this.discount = discount;
    }

    public double getDiscount() {
        return discount;
    }
}

constants/Coupon.java:优惠券的面值

// 优惠券枚举类
public enum Coupon {
    FIVE_OFF(5),    // 优惠 5 元
    TEN_OFF(10),    // 优惠 10 元
    TWENTY_OFF(20); // 优惠 20 元

    private final double discountAmount;

    Coupon(double discountAmount) {
        this.discountAmount = discountAmount;
    }

    public double getDiscountAmount() {
        return discountAmount;
    }
}

Demo

public class Main {
    public static void main(String[] args) {
        //创建一个原始订单
        Order order = new Order(10d, 1, "0001", 10d, new ArrayList<>());
        //创建装饰者子类对象
        /*
             VIP1(0.9), // 折扣 0.9
             VIP2(0.8), // 折扣 0.8
             VIP3(0.7); // 折扣 0.7
         */
        OrderDecorator vipOrderDecorator = new VipOrderDecorator(Vip.valueOf("VIP2"));
        OrderDecorator couponOrderDecorator = new CouponOrderDecorator(Coupon.valueOf("FIVE_OFF"));
        //使用vip和优惠券包装原订单对象,先8折,再减五元(本案例有顺序区别)
        Order vipCouponOrder = couponOrderDecorator.decorator(vipOrderDecorator.decorator(order));
        System.out.println(order);
    }
}

结果:

Order(price=10.0, orderId=1, orderNo=0001, pay=3.0, promotions=[VIP享受8折优惠, 使用5.0元优惠券])
运行结果
运行结果