👉文章示例代码👈

装饰器模式对于笔者来说,印象还是比较深刻的。因为当年笔者考软件设计师的设计模式大题考的就是这个模式,差点阵亡。

定义

动态地为一个对象添加一些额外的职责。

在扩展原有对象功能上,装饰器模式比继承的方式更加灵活。

模式中的角色

  • 抽象构建(Component):定义一个抽象接口(可以是抽象类),用以给对象动态地添加职责。
  • 具体构建(ConcreteComponent):定义一个具体的对象,实现Component接口。
  • 抽象装饰者(Decorator):继承Component,用有Component的职责,同时也可以扩展职责。
  • 具体装饰者(ConcretorDecorator):负责给具体的构建对象添加职责,同时可以定义额外的职责。

场景示例

笔者作为一点点的重度爱好者,这里就以奶茶为例。

创建抽象构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author zhh
* @description 抽象奶茶类
* @date 2020-02-13 23:30
*/
public abstract class AbstractMilkyTea {

/**
* 描述
*/
protected abstract String desc();

/**
* 价格
*/
protected abstract int price();
}

创建具体构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author zhh
* @description 具体奶茶类
* @date 2020-02-13 23:35
*/
public class MilkyTea extends AbstractMilkyTea {

@Override
protected String desc() {
return "奶茶";
}

@Override
protected int price() {
return 7;
}
}

创建抽象装饰者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* @author zhh
* @description 抽象装饰者类
* @date 2020-02-13 23:37
*/
public abstract class AbstractDecorator extends AbstractMilkyTea {

private AbstractMilkyTea abstractMilkyTea;

public AbstractDecorator(AbstractMilkyTea abstractMilkyTea) {
this.abstractMilkyTea = abstractMilkyTea;
}

@Override
protected String desc() {
return this.abstractMilkyTea.desc();
}

@Override
protected int price() {
return this.abstractMilkyTea.price();
}
}

这里抽象装饰者继承了抽象奶茶类。

这个时候,具体奶茶类和抽象装饰者类都作为抽象奶茶类的子类。

我们可以通过具体奶茶类和抽象装饰者类继承的父类(抽象奶茶类)进行组合让这两个子类建立关系。

创建具体装饰者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* @author zhh
* @description 糖装饰者
* @date 2020-02-13 23:58
*/
public class SugarDecorator extends AbstractDecorator {

public SugarDecorator(AbstractMilkyTea abstractMilkyTea) {
super(abstractMilkyTea);
}

@Override
protected String desc() {
return super.desc() + " 加糖";
}

@Override
protected int price() {
return super.price() + 1;
}
}

/**
* @author zhh
* @description 红豆装饰者
* @date 2020-02-14 00:14
*/
public class RedBeanDecorator extends AbstractDecorator {

public RedBeanDecorator(AbstractMilkyTea abstractMilkyTea) {
super(abstractMilkyTea);
}

@Override
protected String desc() {
return super.desc() + " 加红豆";
}

@Override
protected int price() {
return super.price() + 2;
}
}

/**
* @author zhh
* @description 珍珠装饰者
* @date 2020-02-13 23:56
*/
public class PearlDecorator extends AbstractDecorator {

public PearlDecorator(AbstractMilkyTea abstractMilkyTea) {
super(abstractMilkyTea);
}

@Override
protected String desc() {
return super.desc() + " 加珍珠";
}

@Override
protected int price() {
return super.price() + 2;
}
}

测试类及输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @author zhh
* @description 测试类
* @date 2020-02-14 00:21
*/
public class Test {

public static void main(String[] args) {
AbstractMilkyTea abstractMilkyTea = new MilkyTea();
abstractMilkyTea = new SugarDecorator(abstractMilkyTea);
abstractMilkyTea = new PearlDecorator(abstractMilkyTea);
System.out.println(abstractMilkyTea.desc() + " 的销售价格是:" + abstractMilkyTea.price());

abstractMilkyTea = new MilkyTea();
abstractMilkyTea = new RedBeanDecorator(abstractMilkyTea);
abstractMilkyTea = new PearlDecorator(abstractMilkyTea);
System.out.println(abstractMilkyTea.desc() + " 的销售价格是:" + abstractMilkyTea.price());
}
}

测试类输出的结果如下:

奶茶 加糖 加珍珠 的销售价格是:10
奶茶 加红豆 加珍珠 的销售价格是:11

类结构图

以上示例类的结构图如下所示
image.png

总结

适用场景

  • 给一个类添加额外的职责
  • 动态的为一个对象添加功能同时可以动态撤销

优点

  • 比继承更加灵活,易扩展。可以在不改变原有对象的情况下给一个对象扩展功能。
  • 解耦。装饰类和被装饰者可以独立变化,不会相互耦合。

缺点

会导致代码和类的骤增,增加程序复杂性。

参考