Java设计模式—装饰器模式

1、介绍

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能

①、要点

  • 不改变原类文件
  • 不使用继承
  • 动态扩展

②、使用场景:

  • 扩展一个类的功能
  • 动态增加功能,动态撤销

在不想增加很多子类的情况下扩展类。

③、优点:

装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

2、类图(经典)

在装饰模式中的角色有:

  • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象
  • 具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口
  • 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

类图的结构可以变化的地方:

  • Component接口可以是接口也可以是抽象类,甚至是一个普通的父类(这个强烈不推荐,普通的类作为继承体系的超级父类不易于维护)
  • 装饰器的抽象父类Decorator并不是必须的。

3、代码示例

抽象构件角色

1
2
3
4
5
public interface Component {

void operation();

}

具体的接口实现类,也就是俗称的原始对象,或者说待装饰对象

1
2
3
4
5
6
7
8
public class ConcreteComponent implements Component {

@Override
public void operation() {
//TODO 相关的业务代码
}

}

抽象装饰器父类,它主要是为装饰器定义了我们需要装饰的目标是什么,并对Component进行了基础的装饰

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Decorator implements Component {

private Component component;

public Decorator(Component component) {
this.component = component;
}

@Override
public void operation() {
component.operation();
}
}

具体装饰角色

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ConcreteDecoratorA extends Decorator {

public ConcreteDecoratorA(Component component) {
super(component);
}

@Override
public void operation() {
super.operation();

// TODO 相关的修饰业务代码 A
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ConcreteDecoratorB extends Decorator {

public ConcreteDecoratorA(Component component) {
super(component);
}

@Override
public void operation() {
super.operation();

// TODO 相关的修饰业务代码 B
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestDecoratorPattern {

public static void main(String[] args) {

//原来的对象
Component component = new ConcreteComponent();

//装饰成A
Decorator concreteDecoratorA = new ConcreteDecoratorA(component);
//装饰成A以后再装饰成B
Decorator concreteDecoratorB = new ConcreteDecoratorB(concreteDecoratorA);
concreteDecoratorB.operation();


//简写方式
Decorator decorator = new ConcreteDecoratorA(new ConcreteDecoratorB(component));
decorator.operation();

}
}

4、装饰模式的简化类图

如果只有一个ConcreteComponent类,那么可以考虑去掉抽象的Component类(接口),把Decorator作为一个ConcreteComponent子类。如下图所示:

如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。甚至在只有两个ConcreteDecorator类的情况下,都可以这样做。如下图所示: