概述
指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功)的模式。
使用场景
- 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类);
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时。
优缺点
优点
- 装饰者模式可以带来比继承更加灵活性的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果。装饰者模式比继承更具良好的扩展性,完美的遵循开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任。
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
主要角色
- 抽象构件(component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(Concrete component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色:继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
案例实现
UML 类图
被装饰者类
package top.simba1949.decorator;
/**
* @author anthony
* @datetime 2020/5/16 16:16
*/
public interface Component {
/**
* 定一个需要装饰的方法
*/
void operating();
}
package top.simba1949.decorator;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2020/5/16 16:17
*/
@Slf4j
public class ConcreteComponent implements Component {
/**
* 实际需要装饰的方法
*/
@Override
public void operating() {
log.info("------我是可爱的分割线-------");
}
}
装饰者类
package top.simba1949.decorator;
/**
* @author anthony
* @datetime 2020/5/16 16:18
*/
public abstract class Decorator implements Component {
/**
* 以组合的方式进行装饰
*/
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operating() {
component.operating();
}
}
package top.simba1949.decorator;
import lombok.extern.slf4j.Slf4j;
/**
* @author anthony
* @datetime 2020/5/16 16:19
*/
@Slf4j
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
/**
* 进行修饰
*/
@Override
public void operating() {
beforeOperating();
super.operating();
afterOperating();
}
public void beforeOperating() {
log.info("我在分割线上面");
}
public void afterOperating() {
log.info("我在分割线下面");
}
}
测试类
package top.simba1949.decorator;
/**
* 23种设计模式之装饰者模式
*
* @author anthony
* @datetime 2020/5/15 15:55
*/
public class DecoratorApplication {
public static void main(String[] args) {
// 创建一个被装饰的对象
ConcreteComponent concreteComponent = new ConcreteComponent();
// 构建一个具体的装饰者
ConcreteDecorator concreteDecorator = new ConcreteDecorator(concreteComponent);
// 通过装饰者来装饰
concreteDecorator.operating();
}
}
JDK源码解析
IO流中的包装类使用到了装饰者模式。BufferedInputStream, Bufferedoutputstream,BufferedReader,Bufferedwritex。