1. 装饰器模式简介
-
装饰器模式介绍
装饰器模式允许向一个现有的对象添加新功能,同时又不改变其结构。这种类型的设计模式属于结构性模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
-
意图
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
-
主要解决
一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
-
何时使用
在不想增加很多子类的情况下扩展类。
-
如何解决
将具体功能职责划分,同时继承装饰者模式。
-
关键代码
- Component类充当抽象角色,不应该具体实现。
- 修饰类引用和继承Component类,具体扩展类重写父类方法。
-
优点
装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
-
缺点
多层装饰比较复杂
-
使用场景
- 扩展一个类的功能。
- 动态增加功能,动态撤销。
-
注意事项
可替代继承
装饰器模式和适配器模式辨析
装饰器模式和适配器模式很像,但是两者是有一定区别的。装饰器与适配器都有一个别名叫做包装模式,它们看似都是起到包装一个类或对象的作用,但是它们的使用目的很不一样。
适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。
而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的。
详细请看:适配器模式与装饰器模式的区别
2. 装饰器模式的使用
- 装饰器模式的构成
- Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
- ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构建对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
- Decorator(抽象装饰类):它也是抽象构建类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构建对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
- ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责,每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
结构图:
抽象组件
/**
* 抽象组件
*/
public interface Component {
public void operation();
}
具体组件
/**
* 具体组件
*/
public class ConcreteComponent implements Component{
@Override
public void operation() {
System.out.println("biubiubiu");
}
}
抽象装饰类:内部包含一个具体组件实例的引用
/**
* 抽象装饰类
*/
public class Decorator implements Component{
protected Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void operation() {
this.component.operation();
}
}
具体装饰类:抽象装饰类的子类
/**
* 具体装饰类
*/
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component){
super(component);
}
public void operation(){
super.operation();
addedFunction();
}
public void addedFunction(){
System.out.println("为具体构件化角色增加额外的功能addedFunction()");
}
}
测试类
@Test
public void test01(){
Component component = new ConcreteDecorator(new ConcreteComponent());
component.operation();
}
结果
biubiubiu
为具体构件化角色增加额外的功能addedFunction()
3. 总结
-
装饰器模式的优点
- 装饰模式与继承关系的目的都是要扩展对象的功能,但装饰器模式可以提供比继承更多的灵活性。
- 使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,原有代码无需改变,符合开闭原则。
-
装饰器模式的缺点
- 增加了系统的难度,加大学习与理解的难度。
-
装饰器模式的组成部分
- Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
- ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构建对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
- Decorator(抽象装饰类):它也是抽象构建类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构建对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
- ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责,每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
-
装饰器模式和适配器模式辨析
装饰器模式和适配器模式很像,但是两者是有一定区别的。装饰器与适配器都有一个别名叫做包装模式,它们看似都是起到包装一个类或对象的作用,但是它们的使用目的很不一样。
适配器模式的意义是要将一个接口转变成另一个接口,它的目的是通过改变接口来达到重复使用的目的。
而装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有对象的功能,或者改变原有对象的处理方式而提升性能。所以这两个模式设计的目的是不同的。