定义:
装饰者模式动态给一个对象添加额外的职责。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式的特点:
1)装饰者和被装饰对象有相同的超类型。
2)你可以用一个或多个装饰者包装一个对象。
3)既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
4)装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。对象可以在任何时候被装饰,所以可以 在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
类图:
在现实生活中我们经常会遇到诸如装饰者的例子。比如,我们去餐馆吃米粉(RiceNoodle),米粉有粗粉(CoarseRiceNoodle)、细粉(FineRiceNoodle)等分类。米粉的制作过程中又可以添加许多配料( Condiment)以满足客户的口味,配料有牛肉(BeefCondiment)、猪肉(PorkCondiment)等作料。不同种类的米粉加上不同的配料做出来的米粉价格也不一样,如果用具体的子类继承米粉了并考虑到所有组合的话,类的数量是无上限的。而且当配料的价格改变的话,就必须更改含有此配料的子类,这样就不符合类应该对扩展开放,对修改关闭。
米粉(接口/抽象类):
public abstract class RiceNoodle {
String description = "米粉超类";
public String getDescription() {
return description;
}
public abstract double price();
}
粗粉:
public class CoarseRiceNoodle extends RiceNoodle {
//构造方法
public CoarseRiceNoodle() {
description = "粗粉";
}
@Override
public double price() {
return 7.0;
}
}
细粉:
public class FineRiceNoodle extends RiceNoodle {
//构造方法
public FineRiceNoodle() {
description = "细粉";
}
@Override
public double price() {
return 8.0;
}
}
配料(必须实现/继承 米粉 接口/抽象类):
public abstract class CondimentDecorator extends RiceNoodle {
public abstract String getDescription();
}
牛肉配料:
public class BeefCondimentDecorator extends CondimentDecorator {
RiceNoodle riceNoodle; //配料(Decorator)持有米粉(Component)
//构造方法
public BeefCondimentDecorator(RiceNoodle riceNoodle) {
this.riceNoodle = riceNoodle;
}
@Override
public String getDescription() {
return "牛肉" + riceNoodle.getDescription();
}
@Override
public double price() {
return 5.0 + riceNoodle.price();
}
}
猪肉配料:
public class PorkCondimentDecorator extends CondimentDecorator {
RiceNoodle riceNoodle; //配料(Decorator)持有米粉(Component)
//构造方法
public PorkCondimentDecorator(RiceNoodle riceNoodle) {
this.riceNoodle = riceNoodle;
}
@Override
public String getDescription() {
return "猪肉" + riceNoodle.getDescription();
}
@Override
public double price() {
return 3.0 + riceNoodle.price();
}
}
客户端代码:
public class Client {
public static void main(String args[]) {
//创建粗粉对象
RiceNoodle riceNoodle = new CoarseRiceNoodle();
System.out.println(riceNoodle.getDescription()+ “ :价格" + riceNoodle.price());
//创建细粉对象
RiceNoodle riceNoodle2 = new FineRiceNoodle();
//给细粉加作料
riceNoodle2 = new BeefCondimentDecorator(riceNoodle2);
riceNoodle2 = new PorkCondimentDecorator(riceNoodle2);
System.out.println(riceNoodle2.getDescription() + “ 价格:" + riceNoodle2.price());
}
}
输出: 粗粉价格:7.0元
猪肉牛肉细粉价格:16.0元
应用场景:
1.当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰模式。
2.当某个对象的职责经常发生变化或者经常需要动态的增加职责,避免为了适应这样的变化,而增加继承子类扩展的方式,因为这种方式会造成子类膨胀的速度过快,难以控制。