装饰模式介绍
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案
使用场景:
替代继承,扩展一个类的功能
动态的给一个对象添加功能,以及动态的撤销该功能
优点:
动态扩展一个实现类的功能,在不需要添加功能的时候,可以撤销装饰。
装饰类和被装饰类模块间,通过抽象产生依赖,不会相互耦合
装饰模式替换继承,可以避免继承链的子类被影响
源码哪里用到了装饰模式
Java I/O 中的装饰者模式
字符流(InputStream/OutputStream) 和 字节流(Reader/Writer)
Spring Session 中的装饰者模式
ServletRequestWrapper(Response也一样)的装饰者模式
Mybatis 缓存中的装饰者模式
Cache为抽象构件类,PerpetualCache为具体构件类,decorators包下的类为装饰类,这里没有抽象装饰类。
装饰模式与代理模式的区别
装饰模式:侧重给一个实现类动态添加功能,不会对实现类的方法进行过滤拦截
代理模式:侧重将一个实现类的功能,委托给代理类来处理,可以对实现类的方法进行过滤拦截
装饰模式实现
定义一个接口Human,代码如下:
public interface Human {
public void run();
}
抽取一个抽象方法run,人类是可以跑步的,定义一个被装饰的类Man,代码如下:
public class Man implements Human {
@Override
public void run() {
System.out.println("人会跑步");
}
}
定义一个装饰的抽象类,代码如下:
public abstract class AbstractDecorator implements Human{
//持有被装饰类的引用
private Human human;
//构造函数注入被装饰者
public AbstractDecorator(Human human) {
this.human = human;
}
//调用被装饰类的方法
@Override
public void run() {
human.run();
}
}
定义一个装饰的实现类,代码如下:
public class ManDecorator extends AbstractDecorator {
public ManDecorator(Human human) {
//调用父类的构造方法
super(human);
}
//装饰类增加的功能
private void fly() {
System.out.println("人可以飞");
}
//增强了功能的run方法
@Override
public void run() {
super.run();
fly();
}
}
客户端代码如下:
public class Client {
public static void main(String[] args) {
//创建被装饰的类
Human human = new Man();
//创建装饰的类,并添加被装饰类的引用
Human superMan = new ManDecorator(human);
//执行增强后的run方法
superMan.run();
}
}