跳到主要内容

装饰者模式

  • 装饰者模式指的是在不改变原文件和不使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装类对象,也就是装饰着来包裹真实的对象实现的
    因此装饰者可以动态地将责任附加到对象上,提供了比继承更有弹性的扩展功能的方案

结构

  • 组成结构
    • 抽象构件(Component):给出抽象接口或抽象类,以规范准备接收附加功能的对象
    • 具体构件(ConcreteComponent):定义将要接收附加功能的类
    • 抽象装饰(Decorator):装饰者共同要实现的接口,也可以是抽象类,是抽象构件类的子类,维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法
    • 具体装饰(ConcreteDecorator):持有一个 Component 对象,负责给构件对象贴上附加的功能
  • UML
    UML

实现

  • 代码示例
    UML

    // 1. 声明一个原始对象的接口  
    public interface ICoffee {
    void makeCoffee();
    }

    // 2. 构建原始对象(原味咖啡,实现了 ICoffee 接口)
    public class OriginalCoffee implements ICoffee {
    @Override
    public void makeCoffee() {
    System.out.print("原味咖啡 ");
    }
    }

    // 3. 构件装饰者抽象基类,实现与原对象相同的接口 ICoffee,内部持有一个 ICoffee 类型引用,用来接收被装饰的对象
    public abstract class CoffeeDecorator implements ICoffee {
    private ICoffee coffee;
    public CoffeeDecorator(ICoffee coffee){
    this.coffee=coffee;
    }

    @Override
    public void makeCoffee() {
    coffee.makeCoffee();
    }
    }

    // 4. 构建各种装饰者类,都继承自装饰者基类 CoffeeDecorator
    // 加奶的装饰者
    public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(ICoffee coffee) {
    super(coffee);
    }
    @Override
    public void makeCoffee() {
    super.makeCoffee();
    addMilk();
    }
    private void addMilk(){
    System.out.print("加奶 ");
    }
    }
    // 加糖的装饰者
    public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(ICoffee coffee) {
    super(coffee);
    }
    @Override
    public void makeCoffee() {
    super.makeCoffee();
    addSugar();
    }
    private void addSugar(){
    System.out.print("加糖");
    }
    }

    // 5. 客户端使用
    public static void main(String[] args) {
    //原味咖啡
    ICoffee coffee=new OriginalCoffee();
    coffee.makeCoffee();
    System.out.println("");

    //加奶的咖啡
    coffee=new MilkDecorator(coffee);
    coffee.makeCoffee();
    System.out.println("");

    //先加奶后加糖的咖啡
    coffee=new SugarDecorator(coffee);
    coffee.makeCoffee();
    }

特点

  • 优点
    提供比继承更加灵活的方式扩展对象的功能,通过排列组合可以对某个类的一些对象做动态的功能扩展,不需要装饰的对象则可以保持原样
  • 缺点
    类的个数会增加,产生很多装饰者类,增加系统复杂度
  • 装饰者模式和代理模式的区别 一般认为代理模式侧重于使用代理类增强被代理对象的访问,而装饰者模式侧重于使用装饰者类对被装饰对象的功能进行增强
    装饰者模式主要提供一组装饰者类,然后形成一个装饰者栈,动态的对某一个对象不断加强
    代理模式一般不会使用多级代理