装饰者模式(结构型)

一:相关定义

装饰者模式:

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


二:具体的类图和示例

装饰者模式类图:

装饰者模式(结构型)_第1张图片

component是我们要装饰的组件,decorator是我们的装饰器,在这里继承要装饰的组件(使用装饰的目的就是拓展功能而不改变原有的代码;这样,我们新增一个装饰者,客户端依然可以调用原有的组件接口来使用我们的扩展了功能的对象)。

ConcreteDecorator是我们具体的装饰者,如何实现所谓的装饰呢?---通过组合的方式,在构造器获取Component的实例对象并设置要装饰的对象,然后实现继承自基类Component的方法(这里组合了要装饰对象的该方法,并进行新功能添加,即实现了装饰的目的)。


装饰者模式示例图(摘自headfirst设计模式):

装饰者模式(结构型)_第2张图片

该示例是一个关于饮料(beverage)的装饰者模式。下面先看代码:

Beverage(饮料)是一个抽象类,有getDescription()和cost()两个方法;它就是类图中的component,我们要进行装饰的类;

public abstract class Beverage{
    String description = "Unknown Beverage";
    public String getDescription(){
        return description;
    }
    public abstract double cost();
}

CondimentDecractor(调料)抽象类,就是我们的装饰者抽象类;

//首先,必须让CondimentDecorator能够取代Beverage,所以将CondimentDecorator扩展自Beverage类。
public abstract class CondimentDecorator extends Beverage{
    //调料装饰者都必须重新实现getDescription()方法。
    public abstract String getDescription();
}

以上就是我们的基类,下面开始写实现类:

//浓缩咖啡Espresso,扩展自Beverage饮料
public class Espresso extends Beverage{
    //构造器设置饮料描述
    public Espresso(){
        description = "Espresso";
    }
    
    //直接计算Espresso的价钱
    public double cost(){
        return 1.99;
    }
}
public class HouseBlend extends Beverage{
    public HouseBlend(){
        description = "House Blend Coffee";
    }
    public double cost(){
        return 0.89;
    }
}

上面两例就是我们具体的组件(ConcreteComponent),下面我们来实现具体的装饰者(CondimentDecorator):

//摩卡装饰者类,扩展调料装饰者类(此类也扩展自Beverage)
public class Mocha extends CondimentDecorator{
    //让Mocha引用一个Beverage。用一个实例变量记录饮料,也就是被装饰者(利用构造器赋值)。
    Beverage beverage;
    
    public Mocha(Beverage beverage){
        this.beverage = beverage;
    }
    //这里叙述不只是描述饮料(如"Espresso"),而是完整地连调料都描述出来(如"Espresso, Mocha")。
    //利用委托的做法,得到一个叙述,然后在其后加上附加的叙述(如"Mocha")。
    public String getDescription(){
        return beverage.getDescription() + ", Mocha";
    }
    //要计算Mocha饮料的价钱,首先把调用委托给被装饰对象,以计算价钱,然后再加上Mocha的价钱,得到最后结果。
    public double cost(){
        return 0.20 + beverage.cost();
    }
}

终于完成了,下面来进行最后的模拟测试:

 
  
public class StartbuzzCoffee{

    //订一杯Espresso,不需要调料,打印它的描述和价格
    Beverage beverage = new Espresso();
    System.out.println(beverage.getDescription()+" $"+beverage.cost());

    //订一杯黑咖啡,用Mocha装饰它,用第二个Mocha装饰它,用Whip装饰它。
    Beverage beverage2 = new HouseBlend();
    beverage2 = new Mocha(beverage);
    beverage2 = new Mocha(beverage);
    bevarage2 = new Whip(beverage);
    System.out.println(beverage.getDescription()+" $"+beverage.cost());

}


参考书籍:《head first 设计模式》《大话设计模式》

你可能感兴趣的:(装饰者模式(结构型))