装饰器模式

1、定义

装饰器模式 允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰者可以在所委托被装饰者的行为之前或之后加上自己的行为,以达到特定的目的。

属于结构型模式。

装饰器模式由四部分组成:

  • 抽象组件(Component):需要装饰的抽象对象。
  • 具体组件(ConcreteComponent):需要装饰的实体对象
  • 抽象装饰类(Decorator):装饰的抽象类,内含指向抽象组件的引用及装饰者共有的方法。
  • 具体装饰类(ConcreteDecorator):装饰的实体类,负责给实体对象增加新特性。

2、UML图

3、示例

1)Drink接口类:

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

2)Coffee类,需要被装饰的实体对象:

public class Coffee implements Drink {
    final private String description = "coffee";
    //每杯 coffee 售价 10 元
    public float cost() {
        return 10;
    }

    public String getDescription() {
        return description;
    }
}

3) CondimentDecorator 装饰的抽象类:

public abstract class CondimentDecorator implements Drink {
    //对需要被装饰的实体类的引用
    protected Drink decoratorDrink;

    public CondimentDecorator(Drink decoratorDrink) {
        this.decoratorDrink = decoratorDrink;
    }

    public float cost() {
        return decoratorDrink.cost();
    }

    public String getDescription() {
        return decoratorDrink.getDescription();
    }
}

4)Milk 牛奶装饰类:继承了抽象类CondimentDecorator

public class Milk extends CondimentDecorator {
    public Milk(Drink decoratorDrink) {
        super(decoratorDrink);
    }

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

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

5)Sugar 装饰类:

public class Sugar extends CondimentDecorator {
    public Sugar(Drink decoratorDrink) {
        super(decoratorDrink);
    }

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

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

测试代码:

public class CoffeeShop {
    public static void main(String[] args) {
        //点一杯coffee
        Drink drink = new Coffee();
        System.out.println(drink.getDescription() + ":" + drink.cost());
        //加一份奶
        drink = new Milk(drink);
        System.out.println(drink.getDescription() + ":" + drink.cost());
        //加一份糖
        drink = new Sugar(drink);
        System.out.println(drink.getDescription() + ":" + drink.cost());
        //再加一份糖
        drink = new Sugar(drink);
        System.out.println(drink.getDescription() + ":" + drink.cost());
    }
}

输出:

coffee:10.0
coffee milk:12.0
coffee milk sugar:13.0
coffee milk sugar sugar:14.0

4、应用场景

 装饰模式(Decorator)也叫包装器模式(Wrapper)

  装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。

 适用于:1、扩展一个类的功能。 2、动态增加功能,动态撤销。

优点:

  • 扩展对象功能,比继承灵活,不会导致类个数急剧增加
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
  • 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类

缺点:

  • 产生很多小对象。大量小对象占据内存,一定程度上影响性能
  • 装饰模式易于出错,调试排查比较麻烦

Java IO流中有应用