设计模式 - 装饰器模式(Decorator)

定义

动态给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。

类型

结构性模式

适用性

以下情况适用Decorator 模式:

  1. 在不影响其他类的情况下,以动态、透明的方式给单个对象增加职责;
  2. 处理那些可以撤销的对象;
  3. 当不能采用生成子类的方法时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被影藏,或类定义不能用于生成子类。

结构

装饰器结构

参与者

  1. Component: 定义一个对象接口,可以给这些对象动态的添加职责;
  2. ConcreteComponent: 定义一个对象,可以给这个对象添加一些职责;
  3. Decorator: 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。Java 中通常为抽象类。
  4. ConcreteDecorator: 向组件添加职责;

优缺点

  • 优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
  • 缺点:多层装饰比较复杂。

代码样例

1. 组件对象接口Component

public interface Drink {
    float cost();
    String getDescription();
}

2.具体组件ConcreteComponent

public class Coffee implements Drink {
    @Override
    public float cost() {
        return 10;
    }

    @Override
    public String getDescription() {
        return "Coffe";
    }
}

3.抽象装饰器Decorator

public abstract class AbstractDecorator implements Drink {
    Drink decorator;
    AbstractDecorator(Drink decorator) {
        this.decorator = decorator;
    }

    @Override
    public float cost() {
        return decorator.cost();
    }

    @Override
    public String getDescription() {
        return decorator.getDescription();
    }
}

4.具体装饰器ConcreteDecorator

public class MilkDecorator extends AbstractDecorator {
    public MilkDecorator(Drink decorator) {
        super(decorator);
    }

    @Override
    public float cost() {
        return super.cost() + 2;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", Milk";
    }
}

public class SugarDecorator extends AbstractDecorator {
    public SugarDecorator(Drink decorator) {
        super(decorator);
    }

    @Override
    public float cost() {
        return super.cost() + 1;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", Sugar";
    }
}

4.客户端Client

public class Client {
    public static void main(String... args) {
        new Client().test();
    }

    private void test() {
        Drink drink = new Coffee();
        System.out.println(drink.getDescription() + ":" + drink.cost());

        drink = new MilkDecorator(drink);
        System.out.println(drink.getDescription() + ":" + drink.cost());

        drink = new SugarDecorator(drink);
        System.out.println(drink.getDescription() + ":" + drink.cost());

        drink = new SugarDecorator(drink);
        System.out.println(drink.getDescription() + ":" + drink.cost());
    }
}

参考代码

https://github.com/xueyufish/design-pattern-java/tree/master/decorator