定义
装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
角色
- 抽象构件(Component):定义一个接口,来规范准备附加功能的类。
- 具体构件(Concrete Component):将要被附加功能的类,实现抽象构件角色接口。
- 抽象装饰者(Decorator):持有对具体构件的引用,并定义与抽象构件角色一致的接口。
- 具体装饰者(Concrete Decorator):实现抽象装饰者角色,负责为具体构件添加额外功能。
类图
实现
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
Mybatis
Mybatis的二级缓存模块中,使用了装饰者模式的变体,其中将Decorator接口和Component接口合并为一个Component接口,UML类图如下:
由类图可知,PerpetualCache
扮演着Concrete Component(具体组件实现类)的角色,其余的都是装饰类。
实际应用
电商系统中,经常会有限时折扣、红包、抵扣卷以及特殊抵扣金等商品优惠策略,要实现这些组合优惠的功能,最快、最普遍的实现方式就是通过大量的if-else的方式来实现,但这种方式包含了大量的逻辑判断,致使其他开发人员很难读懂业务,并且一旦有新的优惠策略或价格组合策略出现,就需要修改代码逻辑,这时就可以使用装饰者模式,其相互独立、自由组合以及方便动态扩展功能的特性,可以很好的解决if-else方式的弊端。