一、模式定义
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
二、核心角色
-
Component(组件接口)
- 定义被装饰对象的公共接口
-
ConcreteComponent(具体组件)
- 实现基础功能的具体类
-
Decorator(装饰者基类)
- 持有Component引用,实现Component接口
-
ConcreteDecorator(具体装饰者)
- 添加具体装饰功能的实现类
三、经典实现(咖啡店订单系统)
// 1. 组件接口
public interface Coffee {String getDescription();double cost();
}// 2. 具体组件
public class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double cost() {return 1.0;}
}// 3. 装饰者基类
public abstract class CoffeeDecorator implements Coffee {protected final Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double cost() {return decoratedCoffee.cost();}
}// 4. 具体装饰者
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}@Overridepublic double cost() {return super.cost() + 0.5;}
}public class MochaDecorator extends CoffeeDecorator {public MochaDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Mocha";}@Overridepublic double cost() {return super.cost() + 0.7;}
}// 5. 客户端使用
public class CoffeeShop {public static void main(String[] args) {Coffee order = new SimpleCoffee();System.out.println(order.getDescription() + " $" + order.cost());order = new MilkDecorator(order);System.out.println(order.getDescription() + " $" + order.cost());order = new MochaDecorator(order);System.out.println(order.getDescription() + " $" + order.cost());}
}
四、模式结构UML
_________________________| Component ||-------------------------|| + getDescription() || + cost() ||_________________________|▲___________|___________| |_________▼_________ ______▼_______
| ConcreteComponent | | Decorator |
|-------------------| |--------------|
| + getDescription()| | - component |
| + cost() | |______________|
|___________________| ▲_________|_________| |_______▼_______ _______▼_______| ConcreteDecoratorA | | ConcreteDecoratorB ||--------------------| |--------------------|| + addedBehavior() | | + addedBehavior() ||____________________| |____________________|
五、模式优劣分析
优势:
- 动态扩展功能,比继承更灵活
- 符合开闭原则,无需修改现有代码
- 支持多层嵌套装饰
- 不同装饰类可自由组合
劣势:
- 多层装饰增加代码复杂度
- 装饰顺序影响最终结果
- 可能产生大量小类
- 调试困难(需逐层检查装饰)
六、应用场景
- 动态扩展对象功能
(如为图形界面组件添加边框、滚动条) - 撤销功能实现
(通过装饰记录操作历史) - 数据流处理
(Java I/O中的缓冲、加密处理) - 权限控制
(通过装饰添加权限校验层) - 日志记录
(为业务逻辑添加日志装饰)
七、Java标准库应用
Java I/O流典型实现:
// 多层装饰示例
InputStream in = new FileInputStream("data.txt");
in = new BufferedInputStream(in); // 添加缓冲功能
in = new GZIPInputStream(in); // 添加解压缩功能
in = new Base64InputStream(in); // 添加Base64解码// 自定义装饰者示例
class UppercaseInputStream extends FilterInputStream {public UppercaseInputStream(InputStream in) {super(in);}@Overridepublic int read() throws IOException {int c = super.read();return (c == -1) ? c : Character.toUpperCase(c);}
}
八、高级应用技巧
透明性控制
通过接口继承保持装饰透明性:
interface Window {void draw();
}class BasicWindow implements Window { /*...*/ }abstract class WindowDecorator implements Window {protected Window window;// 不暴露额外方法
}
装饰顺序控制
使用建造者模式管理装饰顺序:
public class CoffeeBuilder {private Coffee coffee = new SimpleCoffee();public CoffeeBuilder addMilk() {coffee = new MilkDecorator(coffee);return this;}public Coffee build() {return coffee;}
}
动态移除装饰
实现装饰栈管理:
public class UndoableCoffee implements Coffee {private Deque<Coffee> stack = new ArrayDeque<>();public UndoableCoffee(Coffee coffee) {stack.push(coffee);}public void addDecorator(CoffeeDecorator decorator) {stack.push(decorator);}public void undo() {if (stack.size() > 1) {stack.pop();}}// 实现Coffee接口方法...
}
九、最佳实践建议
- 保持组件接口简洁
避免装饰者需要实现过多无关方法 - 控制装饰层次深度
建议不超过4层装饰 - 优先使用透明装饰
保持装饰前后接口一致 - 注意线程安全问题
对于可变状态装饰器,使用同步控制 - 性能敏感场景慎用
多层装饰可能影响性能(建议结合对象池)