Java 设计模式之装饰器模式(Decorator)

一、装饰器模式

装饰器模式(Decorator Pattern):动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案

类图:

  • Component:组件
  • ConcreteComponent:将要动态加上新行为的对象,扩展自Component
  • Decorator:每个装饰者都有一个组件,就是说装饰者有个实例变量以保存某个Component的引用,这是装饰者共同实现的接口,此类也可以是抽象类
  • ConcreteDecoratorA和ConcreteDecoratorB中有一个实例变量,可以记录所装饰的事物

Java 设计模式之装饰器模式(Decorator)_第1张图片

二、模式详解

用户需求:Starbuzz是以扩张速度最快而闻名的咖啡连锁店,Beverage(饮料)是一个抽象类,cost() 方法是抽象的,下面各种咖啡,购买时加入各种调料
需求分析:每种咖啡都是具体的子类,这里如果一旦有个调料如milk价格变更,那就需要修改所有相关的子类代码,这样下去,项目组就要黄了,这里就涉及一个涉及设计原则:类应该对扩展开放,对修改关闭。
类图设计:

Java 设计模式之装饰器模式(Decorator)_第2张图片

代码示例:

组件Beverage(饮料):

package Decorator;

public abstract class Beverage {
    String description = "UnKnown Beverage";

    public String getDescription() {
        return description;
    }

    // 必须在子类中实现
    public abstract double cost();
}

装饰类CondimentDecorator 

package Decorator;

public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

实现Beverage的具体对象

package Decorator;

public class Espresso extends Beverage {
    public Espresso() {
        // 变量继承自Beverage
        description = "Espresso";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}

实现Beverage的具体对象

package Decorator;

public class HouseBlend extends Beverage {
    public HouseBlend() {
        // 变量继承自Beverage
        description = "HouseBlend";
    }

    @Override
    public double cost() {
        return 0.89;
    }
}

 实现装饰类的调料Milk

package Decorator;

public class Milk extends CondimentDecorator {
    Beverage beverage;

    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }

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

    @Override
    public double cost() {
        return 0.21 + beverage.cost();
    }
}

实现装饰类的调料Mocha

package Decorator;

public class Mocha extends CondimentDecorator {
    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }

    @Override
    public double cost() {
        return 0.20 + beverage.cost();
    }
}

测试类代码

package Decorator;

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());
        Beverage beverage2 = new Mocha(beverage);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
        Beverage beverage3 = new Milk(beverage2);
        System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
    }
}
Espresso $1.99
Espresso, Mocha $2.19
Espresso, Mocha, Milk $2.4

 装饰链:Espresso(1.99)——被Mocha装饰(加上0.2)——被Milk装饰(加上0.21)——最后为 $2.4 。

更多的例子详解——传送门

三、应用示例

装饰器在Java JDK中应用很多,最典型的就是IO,类图

Java 设计模式之装饰器模式(Decorator)_第3张图片

装饰链:FileInputStream——被装饰后BufferedInputStream——被装饰后LineNumberInputStream

你可能感兴趣的:(Java,设计模式)