装饰者模式:
在不改变原有对象的基础上,动态的将功能附加到对象上,提供了比继承更有弹性的替代方案,也体现了开闭原则
注意事项
装饰者模式 VS 继承
目的都是为了要扩展对象的功能,装饰者模式可以提供比继承更多的灵活性
使用装饰着模式,相对于继承而言,需要的类的数目大大减少,再另一方面也会比继承产生更多的对象
使用场景
需要给一个现有类添加职责,但是又不能采用生成子类的方式去扩展的时候
当需要对于现有的一组基本功能进行组合,会产生非常多的功能的时候
当对象的功能要求可以同台的添加,或者说动态的撤销的时候
原理类图
角色分析
- Component: 抽象主体、定义了一个主体的模板
- ConcreteComponentA, B: 具体的主体,里面定义具体的业务逻辑
- Decorator: 装饰者
- ConcreteDecoratorA, B: 封装具体的装饰细节的实现类
java
/**
* @desc 抽象主体
*/
@Data
public abstract class Coffee {
private String desc;
private float price;
public abstract float cost();
}
/**
* @desc 业务实体
*/
public class Cappuccino extends Coffee {
public Cappuccino(){
setPrice(12.2f);
setDesc("卡布奇诺");
}
@Override
public float cost(){
System.out.println("当前价格为: " + getPrice());
return getPrice();
}
}
java
/**
* @desc 装饰器
*/
public class Decorator extends Coffee{
private Coffee coffee;
public Decorator(Coffee coffee){
this.coffee = coffee;
}
// 重新计算方法: 递归实现
@Override
public float cost() {
return super.getPrice() + coffee.cost();
}
@Override
public String getDesc(){
return super.getDesc() + coffee.getDesc();
}
}
/**
* @desc 装饰细节: 牛奶
*/
public class Milk extends Decorator {
public Milk(Coffee coffee) {
super(coffee);
setDesc("加了一份牛奶,");
setPrice(2.3f);
}
}
/**
* @desc 装饰器: 糖
*/
public class Sugar extends Decorator{
public Sugar(Coffee coffee) {
super(coffee);
setDesc("加了份糖,");
setPrice(1.5f);
}
}
java
/**
* @desc 消费者
*/
public class CoffeeStore {
public static void main(String... args){
// 卡布奇诺, 1份牛奶,2份糖
Coffee order = new Cappuccino();
System.out.println("当前描述: " + order.getDesc() + " 当前价格: " + order.cost());
order = new Milk(order);
System.out.println("当前描述: " + order.getDesc() + " 当前价格: " + order.cost());
order = new Sugar(order);
order = new Sugar(order);
System.out.println("当前描述: " + order.getDesc() + " 当前价格: " + order.cost());
}
}