设计模式: 装饰器

786 阅读2分钟

装饰者模式:

在不改变原有对象的基础上,动态的将功能附加到对象上,提供了比继承更有弹性的替代方案,也体现了开闭原则

注意事项

装饰者模式 VS 继承

目的都是为了要扩展对象的功能,装饰者模式可以提供比继承更多的灵活性
使用装饰着模式,相对于继承而言,需要的类的数目大大减少,再另一方面也会比继承产生更多的对象

使用场景

需要给一个现有类添加职责,但是又不能采用生成子类的方式去扩展的时候
当需要对于现有的一组基本功能进行组合,会产生非常多的功能的时候
当对象的功能要求可以同台的添加,或者说动态的撤销的时候

原理类图

class.png

角色分析

  • Component: 抽象主体、定义了一个主体的模板
  • ConcreteComponentA, B: 具体的主体,里面定义具体的业务逻辑
  • Decorator: 装饰者
  • ConcreteDecoratorA, B: 封装具体的装饰细节的实现类

代码实现

/**  
  * @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();  
    } 
}  
  
/**  
  * @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("加了1份糖,");  
        setPrice(1.5f);  
    }  
}  
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());  
    }  
}  
当前价格为: 12.2
当前描述: 卡布奇诺 当前价格: 12.2
当前价格为: 12.2
当前描述: 加了一份牛奶,卡布奇诺 当前价格: 14.5
当前价格为: 12.2
当前描述: 加了1份糖,加了1份糖,加了一份牛奶,卡布奇诺 当前价格: 17.5