装饰器模式
...大约 2 分钟
装饰是一种结构设计模式, 允许你通过将对象放入特殊封装对象中来为原对象增加新的行为。
由于目标对象和装饰器遵循同一接口, 因此你可用装饰来对对象进行无限次的封装。 结果对象将获得所有封装器叠加而来的行为。
使用示例: 装饰在 Java 代码中可谓是标准配置, 尤其是在与流式加载相关的代码中。
Java 核心程序库中有一些关于装饰的示例:
java.io.InputStream
、OutputStream
、Reader
和Writer
的所有代码都有以自身类型的对象作为参数的构造函数。java.util.Collections
;checkedXXX()
、synchronizedXXX()
和unmodifiableXXX()
方法。javax.servlet.http.HttpServletRequestWrapper
和HttpServletResponseWrapper
识别方法: 装饰可通过以当前类或对象为参数的创建方法或构造函数来识别。
订单优惠券与会员机制
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元优惠券])
