1、基本介绍
装饰器设计模式是一种结构型设计模式,它允许动态地为对象添加新的行为。它通过创建一个包装器来实现,即将对象放入一个装饰器类中,再将装饰器类放入另一个装饰器类中,以此类推,形成一条包装链。这样就可以在不改变原有对象的情况下,动态地添加新的行为或修改原有行为
2、案例
1、定义一个抽象(抽象类或接口),作为被装饰对象的基类
public interface Component {
void operation();
}
2、定义一个被装饰对象,实现基类
public class ConcreteComponent implements Component{
@Override
public void operation() {
System.out.println("我是被装饰对象");
}
}
3、定义一个抽象装饰器类,实现基类,并将被装饰对象作为属性
public class Decorator implements Component{
// 持有被装饰对象,装饰器模式通过组合的方式进行装饰而非继承
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
4、定义第一个装饰器/包装器,基础抽象装饰器类
public class DecoratorOne extends Decorator{
public DecoratorOne(Component component) {
// 给父类Component赋值
super(component);
}
@Override
public void operation() {
// 对被装饰器类做方法前后做增强
System.out.println("装饰器一方法前增强");
super.operation();
System.out.println("装饰器一方法后增强");
}
}
5、定义第二个装饰器/包装器,基础抽象装饰器类
public class DecoratorTwo extends Decorator{
public DecoratorTwo(Component component) {
// 给父类Component赋值
super(component);
}
@Override
public void operation() {
// 对被装饰器类做方法前后做增强
System.out.println("装饰器二方法前增强");
super.operation();
System.out.println("装饰器二方法后增强");
}
}
6、装饰器模式的使用
public static void main(String[] args) {
// 1、创建一个原始对象/被装饰对象
Component component = new ConcreteComponent();
// 2、进行第一次包装,此时的component实例DecoratorOne(用包装类替换了原始类),已进行第一次增强
component = new DecoratorOne(component);
// 3、进行第二次包装,此时的component实例DecoratorTwo,已进行第二次增强
component = new DecoratorTwo(component);
// 4、调用增强后的方法
component.operation();
}
7、运行结果
装饰器二方法前增强
装饰器一方法前增强
我是被装饰对象
装饰器一方法后增强
装饰器二方法后增强
3、一个极易理解的使用场景 - IO流
InputStream inputStream = new FileInputStream("D://aa.txt");
// 通过包装类让inputStream支持带混存功能的读取数据
inputStream = new BufferedInputStream(inputStream);
// 继续通过包装类进行增强
inputStream = new DataInputStream(inputStream);
4、都是对原始类做增强,装饰器模式和代理模式有什么区别?
先回顾一下代理模式的核心功能:1、屏蔽被代理对象。2、对被代理类做增强
装饰器模式主要解决继承关系过于复杂的问题,通常通过组合来代替继承。而不需要像代理对象屏蔽原始对象(直接操作代理对象)。而装饰器设计模式,你想使用原始对象就使用原始对象,想使用包装对象就使用包装对象
装饰器类附加的是跟原始类相关功能增强(比如给查询缓存的对象添加LRU、LFU等过期策略),而代理类通常是附加跟原始类无关的功能(比如打印日志、权限控制等)
5、为什么要用组合来代替继承?
请了解组合优于继承设计原则