模式动机
一般有两种方式可以给一个类或者对象增加行为:
- 继承机制,常用不做解释
- 关联机制,即将一个类的对象嵌入到另一个对象中,由另一个对象决定是否调用嵌入对象的行为来扩展自己的行为,我们称这个接入嵌入对象的类为装饰器。
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同
。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展
。
模式定义
动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。
模式结构
装饰模式包含如下角色:
- Component: 抽象构件
- ConcreteComponent: 具体构件
- Decorator: 抽象装饰类
- ConcreteDecorator: 具体装饰类
时序图
代码实现
ps:对于时序图和类图理解不透彻可以通过阅读代码理清思路。
//构件类
public interface Component {
public void operation();
}
//具体构件类
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("制造了一个木栏杆");
}
}
//抽象装饰类
public abstract class Decorator implements Component{
private Component component;
public Decorator(Component component){
this.component=component;
}
@Override
public void operation() {
component.operation();
}
}
//具体装饰类
public class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("我们给木栏杆涂上红漆");
}
}
public class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("我们给木栏杆涂上绿漆");
}
}
//客户端类
public class Client {
public static void main(String[] args) {
Component component=new ConcreteComponent();
//造一个红栏杆
ConcreteDecoratorA red=new ConcreteDecoratorA(component);
red.operation();
//造一个绿栏杆
ConcreteDecoratorB green=new ConcreteDecoratorB(component);
green.operation();
//造一个花栏杆
Decorator color=new ConcreteDecoratorB(red);
color.operation();
}
}
模式分析
- 装饰模式是一种关联关系,相较于继承关系,具有较好的松耦合性,因此系统更利于维护。缺点在于,关联关系相比于继承关系会创建更多的对象。
- 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。
模式优缺点
优点
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。相较于继承,装饰模式更加灵活
- 符合开闭原则,新增新的装饰类与构件类不需要修改已有代码,扩展灵活
缺点
- 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难。多层装饰比较复杂。
- 使用装饰模式进行系统设计时将产生很多小对象,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。