Head First 设计模式(四)装饰者模式

定义

装饰者模式动态的将责任附加到对象,若要拓展功能,装饰者提供了比继承更有弹性的替代方案

按我的理解翻译:

当子类的行为增加时,继承只能修改代码,而组合动态可以在不修改代码的情况下动态进行扩展。

场景举例

现在有一家咖啡店要提供四种咖啡:HouseBlend、DarkRoast、Decaf和Espresso。这四种咖啡可以加任意调料组合成不同的饮料,例如牛奶摩卡浓缩咖啡(MilkMochaEspresso)

如果我们用继承实现这样的饮料框架,它将是:

这里写图片描述

父类通过设置调料的布尔值来控制cost方法计算出所有调料的价格,然后子类cost方法算出饮料价格+父类cost计算的调料价格,获取真正的饮料价格。

我们很容易发现这样的实现不优雅,毛病很多。首先,每次拓展一种新饮料时,我们不得不修改父类的代码,而这样的修改可能影响到原有功能。

如何解决?我们先放出一个新的设计模式:

类应该对扩展开放,对修改关闭

也就是我们应该尽量让我们的代码具有拓展性,增加新需求时不需要更改老代码就可以拓展。

这里就需要用到装饰者模式的组合来替换基础了。

代码Demo

首先看一下装饰者模式的框架:

装饰者模式分为两个部分:组件(Component)和装饰者(Decorator),其中装饰者和组件的继承同一个类。
装饰者中组合了组件,这样就可以运用代理的思想对组件的方法进行修改和拓展,且不用修改原有代码。

我们以上面的咖啡店为例,看下装饰者模式的框架:

四种咖啡为组件,调料为装饰者,装饰者可以重复装饰装饰者,这样就获取了加了若干调料的饮料类。

好,现在放上Demo代码:
父类:

public abstract class Beverage {
    public String name;

    public String getName() {
        return this.name;
    }

    public abstract double cost();
}

具体组件:

/**
 * 浓缩咖啡
 */
public class Espresso extends Beverage{

    public Espresso() {
        this.name = "espresso";
    }

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

/**
 * 深焙咖啡
 */
public class DarkRoast extends Beverage{
    public DarkRoast() {
        this.name = "darkRoast";
    }

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

调料装饰者:

/**
 * 调料装饰父类
 */
public abstract class CondimentDecorator extends Beverage{
    Beverage beverage;

    @Override
    public abstract String getName() ;

}

/**
 * 牛奶调料
 */
public class Milk extends CondimentDecorator{

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


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


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

}

/**
 * 摩卡调料
 */
public class Mocha extends CondimentDecorator{

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


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


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

}

咖啡店测试:

/**
 * 咖啡店
 */
public class CoffeeHouse {
    public static void main(String[] args) {
        //来一杯  深焙咖啡
        Beverage beverage = new DarkRoast();
        System.out.println(beverage.getName()+" $"+beverage.cost());
        //来一杯  加牛奶的浓缩咖啡
        Beverage beverage2 = new Espresso();
        beverage2 = new Milk(beverage2);
        System.out.println(beverage2.getName()+" $"+beverage2.cost());
        //来一杯 加摩卡、牛奶的深焙咖啡
        Beverage beverage3 = new DarkRoast();
        beverage3 = new Mocha(beverage3);
        beverage3 = new Milk(beverage3);
        System.out.println(beverage3.getName()+" $"+beverage3.cost());

    }
}/**output:
darkRoast $1.5
espresso, Milk $3.8
darkRoast, Mocha, Milk $3.3
*/

JAVA中的装饰者模式

Java源码中许多地方运用到了装饰者模式,例如IO相关类:

猜你喜欢

转载自blog.csdn.net/z55887/article/details/69488302