装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更灵活。UML结构图如下:
下面以喝咖啡,可以往咖啡中加糖、加茶、加牛奶来进行举例:
参与角色:
- 抽象接口
- 具体对象,即可以进行装饰的具体对象
- 抽象装饰类
- 具体装饰类
抽象接口
/**
* 咖啡 抽象接口
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public abstract class CoffeeComponent {
/**
* 喝咖啡
*/
public abstract void eat();
}
具体对象
/**
* 雀巢咖啡 具体的对象,可以给这个对象加一些职责
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class NestleCoffeeComponent extends CoffeeComponent{
private String name;
public NestleCoffeeComponent(String name){
this.name = name;
}
@Override
public void eat() {
System.out.print("喝" + name + "咖啡");
}
}
抽象装饰类
/**
* 抽象装饰类
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public abstract class Decorator extends CoffeeComponent{
protected CoffeeComponent component;
public void setComponent(CoffeeComponent component){
this.component = component;
}
@Override
public void eat() {
component.eat();
}
}
具体装饰类
/**
* 具体装饰类-糖类
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class Sugar extends Decorator{
@Override
public void eat() {
System.out.print("加糖、");
super.eat();
}
}
/**
* 具体装饰类-牛奶类
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class Milk extends Decorator{
@Override
public void eat() {
System.out.print("加牛奶、");
super.eat();
}
}
/**
* 具体的装饰类-茶类
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class Tea extends Decorator{
@Override
public void eat() {
System.out.print("加茶、");
super.eat();
}
}
测试类
public class Main {
/**
* 装饰模式
* 1.往咖啡中加糖、牛奶, 加茶
* @param args
*/
public static void main(String[] args) {
/**
* 1. 抽象接口 CoffeeComponent
* 2. 具体对象,即可以进行装饰的具体对象 NestleCoffeeComponent...
* 3. 抽象装饰类 Decorator
* 4. 具体装饰类 Sugar、Milk、Tea...
*/
NestleCoffeeComponent coffee = new NestleCoffeeComponent("雀巢");
Sugar sugar = new Sugar();
Milk milk = new Milk();
Tea tea = new Tea();
// 加糖
sugar.setComponent(coffee);
// 加茶
tea.setComponent(sugar);
// 加牛奶
milk.setComponent(tea);
milk.eat();
}
}
装饰模式不是稳定,可以随意装饰,上述的加糖、加牛奶、加茶的顺序可以随意组装。
装饰模式总结:
- 何时使用
在不想增加很多子类的情况下扩展类时 - 方法
将具体功能职责划分,同时继承装饰者模式 - 优点
1、装饰类和被装饰类可以独立发展,而不会相互耦合。它有效地把类的核心职责和装饰功能分开了;
2、装饰模式是继承关系的一个替代方案;
3、装饰模式可以动态地扩展一个实现类的功能; - 缺点
多层装饰比较复杂。比如我们现在有很多层装饰,出了问题,一层一层检查,最后发现是最里层的装饰出问题了,想想工作量都害怕 - 使用场景
1、需要扩展一个类的功能时
2、需要动态地给一个对象增加功能,并可以动态地撤销时
3、需要为一批的兄弟类进行改装或加装功能时