- 定义
在不改变原有对象的基础上,动态的给对象增加新的功能。提供了比继承更加弹性的方案。
-
通用类图
- 我对装饰器模式的理解
- 组件
装饰器模式中包括抽象组件(Component)、抽象装饰者(Decorator)、具体组件(ConcreteComponent)、具体装饰者(ConcreteDecorator)四种组件。
- 思想
- 定义一个顶层的抽象组件,在抽象组件中定义一个组件中的属性和方法。
- 让装饰器和具体的组件都去继承这个抽象组件,使它们在同一继承体系下。在抽象装饰器的构造方法中传入一个组件,从而可以获取被装饰的组件的实例。重写抽象组件中定义的方法。
- 实现具体的装饰器,重写抽象组件中的方法,可以在具体逻辑处理之前或者之后增加功能。
- 一次扩展实现
背景:现有一个煎饼果子类,只有基础的煎饼果子该有的东西,并且已经上线。现在想在不修改这个类的前提下进行功能扩展,比如加鸡蛋,加香肠。
/**
* 现有的煎饼果子类,不能添加任何功能,只有名称和基础价格
*/
public class BaseBattercake{
public String getMsg() {
return "煎饼果子";
}
public int getPrice() {
return 5;
}
}
设计思路:
- 定义一个抽象装饰器,继承该类。
- 定义具体的装饰,鸡蛋装饰和香肠装饰。
//抽象装饰器
public abstract class BattercakeDecorator extends BaseBattercake {
private BaseBattercake battercake;
public BattercakeDecorator(BaseBattercake battercake) {
this.battercake = battercake;
}
@Override
public String getMsg() {
return this.battercake.getMsg();
}
@Override
public int getPrice() {
return this.battercake.getPrice();
}
}
//鸡蛋装饰器
public class EggDecorator extends BattercakeDecorator {
public EggDecorator(BaseBattercake battercake) {
super(battercake);
}
@Override
public String getMsg() {
return super.getMsg() + "+ 一个鸡蛋";
}
@Override
public int getPrice() {
return super.getPrice() + 1;
}
}
//香肠装饰器
public class SausageDecorator extends BattercakeDecorator {
public SausageDecorator(BaseBattercake battercake) {
super(battercake);
}
@Override
public String getMsg() {
return super.getMsg() + "+ 一个香肠";
}
@Override
public int getPrice() {
return super.getPrice() + 2;
}
}
public class Test {
public static void main(String[] args) {
BaseBattercake battercake = new BaseBattercake();
System.out.println(battercake.getMsg() + battercake.getPrice());
BattercakeDecorator decorator = new EggDecorator(battercake);
decorator = new EggDecorator(decorator);
decorator = new SausageDecorator(decorator);
System.out.println(decorator.getMsg() +",¥"+ decorator.getPrice());
}
}
- 优缺点
优点:
- 装饰器模式是继承的有力补充,比继承更加灵活,在不改变原有功能的基础上,进行功能的扩展。
- 可以使用不同的装饰类进行扩展,从而达到不同的效果。
- 使用装饰器完全符合开闭原则。
缺点:
- 会出现更多的代码和更多的类,增加系统的复杂度。
- 动态装饰时,多层装饰更复杂。
- 与代理模式的对比
扩展面不同。装饰器模式强调的是concreteComponent功能的扩展,主体对象是concreteComponent,着重类功能的变化。代理模式强调对代理过程的控制,Proxy完全掌握对RealSubject的控制,主体对象是Proxy。