一,装饰者模式
装饰者模式,举一个简单的例子,JDK中的IO就充分使用了装饰者模式,IO中有两个顶层接口:InputStream和OutputStream。其他所有相关的字符流和字节流都是实现自该类,并且在全部实现类中,存在部分类的功能是对其他实现类功能增强,例如输入输入流和对应的Buffered输入输出流。
所以,简单来说,装饰者模式是对原有功能的增强。在不改变原有结构的基础上,创造出类结构的强一致性,增强类或者也可以称为包装类,持有原有原有类的引用,对原有类的部分数据结构进行打开重构。装饰者模式装饰的是原有类的类型而不是原有类的行为
二,UML类图
* Componment : 装饰行为的顶层接口,用来保证装饰对象的强一致性;
* ContreteComponment : 原有实现类,整体包装是对该类进行包装;
* Decorator : 包装类的顶层接口,并继承整个行为的顶层接口,保证强一致性;
* ConcreteDecoratorA : 具体的包装类,用来对原有类进行类型包装;
三,代码实现
1,实体类
public class Order {
private String orderId;
private Double cost;
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Double getCost() {
return cost;
}
public void setCost(Double cost) {
this.cost = cost;
}
@Override
public String toString() {
return "Order{" +
"orderId='" + orderId + '\'' +
", cost=" + cost +
'}';
}
}
2,顶层接口
public interface IMarketCost {
public void cost();
public Order getOrder();
}
3,原有类
public class StandardCost implements IMarketCost {
private Order order;
public StandardCost(Order order) {
this.order = order;
}
@Override
public void cost() {
System.out.println("---------原订单---------");
System.out.println(order);
}
@Override
public Order getOrder() {
return order;
}
}
可以看出原有类没有任何的折扣优惠
4,包装类
现在超市搞活动,存在普通用户的优惠活动和VIP用户的优惠活动两种方式,需要根据优惠用户类型和花费金额不同采取不同的优惠方式,这时候就需要对原有类进行包装处理;
* 包装类顶层接口
public interface ICountMarketCost extends IMarketCost {
}
* 折扣包装类
public class DiscountCost implements ICountMarketCost {
private IMarketCost marketCost;
public DiscountCost(IMarketCost marketCost) {
this.marketCost = marketCost;
}
@Override
public Order getOrder() {
return marketCost.getOrder();
}
@Override
public void cost() {
Order order = marketCost.getOrder();
Double cost = order.getCost();
if (cost > 200) {
order.setCost(cost * 0.9);
}
System.out.println("----------折扣销售----------");
System.out.println(order);
}
}
* VIP包装类
public class VIPCost implements ICountMarketCost {
private IMarketCost marketCost;
public VIPCost(IMarketCost marketCost) {
this.marketCost = marketCost;
}
@Override
public Order getOrder() {
return marketCost.getOrder();
}
@Override
public void cost() {
Order order = marketCost.getOrder();
Double cost = order.getCost();
if (cost < 100) {
cost *= 0.9;
} else if (cost < 200) {
cost *= 0.8;
} else {
cost *= 0.7;
}
order.setCost(cost);
System.out.println("---------VIP订单--------");
System.out.println(order);
}
}
5,测试类
public class DecorateTest {
public static void main(String[] args) {
Order order = new Order();
order.setOrderId(UUID.randomUUID().toString());
order.setCost(300.00);
// 原订单
IMarketCost standCost = new StandardCost(order);
standCost.cost();
// 折扣订单
ICountMarketCost discountCost = new DiscountCost(standCost);
discountCost.cost();
// VIP订单
standCost.getOrder().setCost(300.00);
ICountMarketCost vipCost = new VIPCost(standCost);
vipCost.cost();
}
}
这样包装之后,如果该超市以后针对不同的时期要举办不同的活动,只需要新建包装类实现包装接口,在该实现类中定义优惠详情,就可以完成整体活动的添加和变更, 而不需要对原有代码进行转换;