一、装饰器模式是什么?
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。人话:点咖啡加配料
二、模式分析
1.四个角色
- 抽象组件(Component):可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为;
- 抽象装饰器(Decorator):通用的装饰 ConcreteComponent 的装饰器,其内部必然有一个属性指向 Component抽象组件;其实现一般是一个抽象类,主要是为了让其子类按照其构造形式传入一个 Component抽象组件,这是强制的通用行为(当然,如果系统中装饰逻辑单一,并不需要实现许多装饰器,那么我们可以直接省略该类,而直接实现一个 具体装饰器(ConcreteDecorator) 即可);
- 具体组件(ConcreteComponent):实现/继承 Component 的一个具体对象,也即 被装饰对象;
- 具体装饰器(ConcreteDecorator):Decorator 的具体实现类,理论上,每个 ConcreteDecorator 都扩展了 Component 对象的一种功能;
2.案例
- 抽象组件
//抽象组件
public interface Component {
void dress();
}
- 抽象装饰器
//抽象装饰器(Decorator
public abstract class Decorator implements Component {
Component mPerson;
// 构造方法强制子类构造必须传入一个Component
public Decorator(Component person) {
this.mPerson = person;
}
@Override
public void dress() {
this.mPerson.dress();
}
}
- 具体组件
//具体组件(ConcreteComponent)
public class Man implements Component{
@Override
public void dress() {
System.out.println("穿了内裤!");
}
}
- 具体装饰器
//具体装饰器(ConcreteDecorator)
public class TrousersDecorator extends Decorator{
public TrousersDecorator(Component person) {
super(person);
}
@Override
public void dress() {
super.dress();
this.dressTrousers();
}
private void dressTrousers() {
System.out.println("穿上裤子了!");
}
}
- 测试类
public class test {
public static void main(String[] args) {
Component man = new Man();
man.dress();
System.out.println("==========");
System.out.println("增加裤子适配器");
man = new TrousersDecorator(man);
man.dress();
}
}
- 结果
三、装饰器模式的优缺点
优点
- 动态扩展类功能,比类继承灵活,且对客户端透明;
- 继承关系的一种替代方案。相比与类继承的父子关系,装饰模式 更像是一种-组合关系(is-a);
- 可以对同一个被装饰对象进行多次装饰,创建出不同行为的复合功能;
缺点
- 多层装饰比较复杂(灵活的同时会带来复杂性的增加);
- 装饰嵌套过多,会产生过多小对象(每个装饰层都创建一个相应的对象);
- 装饰嵌套过多,易于出错,且调试排查比较麻烦(需要一层一层对装饰器进行排查,以确定是哪一个装饰层出错);