定义
在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)
类型
结构型
适用场景
- 扩展一个类的功能或者给一个类添加附加职责
- 给一个对象动态的添加功能,或动态撤销功能。
优点
- 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能。(继承在扩展功能是静态的,必须在编译时就确定好,而使用装饰者可以在运行时决定,装饰者也建立在继承的基础之上的)
- 通过使用不同装饰类以及这些类的排列组合,可以实现不同的效果。
- 符合开闭原则
缺点
- 会出现更多的代码,更多的类,增加程序的复杂性。
- 动态装饰时,多层装饰时会更复杂。(使用继承来拓展功能会增加类的数量,使用装饰者模式不会像继承那样增加那么多类的数量但是会增加对象的数量,当对象的数量增加到一定的级别时,无疑会大大增加我们代码调试的难度)。
实例
咖啡馆订单项目:
1)咖啡种类:Espresso、ShortBlack(浓缩)、LongBlack、Decaf (无糖)。
2)调料:Milk、Soy、Chocolate 。
代码实现
注意:部分咖啡,调料没有实现,其同已实现的咖啡,调料。
关键点:Beverage beverage的调用
抽象类
public abstract class Beverage {
public String description="Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
咖啡类
public class Espresso extends Beverage {
public Espresso(){
description="Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
public HouseBlend(){
description="HouseBlend";
}
@Override
public double cost() {
return 1.89;
}
}
抽象类—装饰者(调料)
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
具体装饰者—调料
public class Mocha extends CondimentDecorator {
public 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();
}
}
咖啡订购(main)
public class StarbuzzCoffee {
public static void main(String args[]){
Beverage beverage=new Espresso();
//单品咖啡
System.out.println("单品咖啡");
System.out.println(beverage.getDescription()+"$"+beverage.cost());
beverage=new Mocha(beverage);
//加入Mocha的咖啡
System.out.println("加入Mocha的咖啡");
System.out.println(beverage.getDescription()+"$"+beverage.cost());
}
}
运行结果