装饰模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在不修改现有对象结构的情况下,动态地给对象添加新的功能。这种模式通过将对象包装在装饰器类中来实现功能的扩展,从而提供了一种比继承更灵活的替代方案。
核心思想
- 组合而非继承:使用组合的方式而不是通过继承来扩展对象的功能。
- 透明性:客户端代码可以透明地使用被装饰的对象,就像使用原始对象一样。
- 递归包装:可以多次应用装饰器,形成一个装饰器链,每个装饰器都可以增加额外的行为。
优点
- 灵活性高:可以在运行时动态地添加或移除功能。
- 遵循开闭原则:对扩展开放,对修改关闭,即可以在不修改原有代码的基础上增加新功能。
- 避免类爆炸:相比于通过继承来实现多种功能组合,装饰器模式减少了子类的数量,避免了类层次结构的过度膨胀。
缺点
- 复杂度增加:随着装饰器数量的增加,系统的复杂性也会增加,可能会导致难以理解和维护。
- 多层装饰:如果装饰器层级过多,可能会影响性能,并且调试变得困难。
使用场景
- 当需要向一个对象添加职责,但又不想使用子类时。
- 当希望能够在运行时动态地为对象添加或移除功能。
- 当有多个可选的行为需要组合应用到对象上时,例如文本编辑器中的格式化选项、窗口系统的边框和滚动条等。
实现方式
装饰器模式通常包含以下几个角色:
- Component(组件):定义了一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent(具体组件):定义了一个具体的对象,也可以给这个对象添加一些职责。
- Decorator(装饰器):持有一个Component对象的引用,并定义了一个与Component接口一致的接口。
- ConcreteDecorator(具体装饰器):向组件添加职责。
示例:
组件
java
public interface Costume {
void wear();
}
具体组件
java
@Slf4j
public class Person implements Costume {
private String name;
public Person(String name) {
this.name = name;
}
@Override
public void wear() {
log.info("装扮的{}" ,name);
}
}
装饰器
java
public abstract class CostumeDecorator implements Costume {
protected Costume costume;
protected CostumeDecorator(Costume costume) {
this.costume = costume;
}
@Override
public void wear() {
Optional
.ofNullable(costume)
.ifPresent(Costume::wear);
}
}
装饰器具体实现:
java
@Slf4j
public class JeansDecorator extends CostumeDecorator{
private String color;
public JeansDecorator(Costume costume,String color) {
super(costume);
this.color = color;
}
@Override
public void wear() {
log.info("{}牛仔裤",color);
super.wear();
}
}
@Slf4j
public class TShirtDecorator extends CostumeDecorator {
protected TShirtDecorator(Costume costume) {
super(costume);
}
@Override
public void wear() {
log.info("T恤");
super.wear();
}
}
调用
java
public class Main {
public static void main(String[] args) {
Costume person = new Person("张三");
person = new TShirtDecorator(person);
person = new JeansDecorator(person,"蓝色");
person.wear();
}
}
打印
java
11:11:03.010 [main] INFO com.lj.decorator.Jeans -- 蓝色牛仔裤
11:11:03.015 [main] INFO com.lj.decorator.TShirt -- T恤
11:11:03.015 [main] INFO com.lj.decorator.Person -- 装扮的张三