人的知识就好比一个圆圈,圆圈里面是已知的,圆圈外面是未知的。你知道得越多,圆圈也就越大,你不知道的也就越多。

0%

设计模式--装饰者模式

定义

装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

角色

  • 抽象构件(Component):定义一个接口,来规范准备附加功能的类。
  • 具体构件(Concrete Component):将要被附加功能的类,实现抽象构件角色接口。
  • 抽象装饰者(Decorator):持有对具体构件的引用,并定义与抽象构件角色一致的接口。
  • 具体装饰者(Concrete Decorator):实现抽象装饰者角色,负责为具体构件添加额外功能。

类图

Decorator UML

实现

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
public abstract class Component {

/**
* 操作
*/
abstract void operation();
}

public class ConcreteComponent extends Component {

@Override
public void operation() {
System.out.println("real operation");
}
}

public abstract class Decorator extends Component {
private Component component;

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

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

public class ConcreteDecoratorA extends Decorator {

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

@Override
void operation() {
newBehavior();
super.operation();
}

private void newBehavior() {
System.out.println("new behavior A");
}
}

public class ConcreteDecoratorB extends Decorator {

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

@Override
void operation() {
newBehavior();
super.operation();
}

private void newBehavior() {
System.out.println("new behavior B");
}
}

优缺点

优点

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

缺点

  • 多层装饰比较复杂

使用场景

  • 动态扩展类的功能

模式应用

JAVA IO

InputStream UML

Mybatis

Mybatis的二级缓存模块中,使用了装饰者模式的变体,其中将Decorator接口和Component接口合并为一个Component接口,UML类图如下:
Cache UML
由类图可知,PerpetualCache扮演着Concrete Component(具体组件实现类)的角色,其余的都是装饰类。

实际应用

电商系统中,经常会有限时折扣、红包、抵扣卷以及特殊抵扣金等商品优惠策略,要实现这些组合优惠的功能,最快、最普遍的实现方式就是通过大量的if-else的方式来实现,但这种方式包含了大量的逻辑判断,致使其他开发人员很难读懂业务,并且一旦有新的优惠策略或价格组合策略出现,就需要修改代码逻辑,这时就可以使用装饰者模式,其相互独立、自由组合以及方便动态扩展功能的特性,可以很好的解决if-else方式的弊端。

小礼物走一走,来 Github 关注我