装饰器模式(Decorator Pattern)是一种结构型设计模式
,允许通过将对象放入包含行为的特殊封装对象中来动态地添加新功能
。它通过组合替代继承,提供了比继承更灵活的功能扩展方式,同时遵循开闭原则。
核心思想
动态扩展
:在不修改原有类的情况下,通过包装对象(装饰器)来增强功能。透明性
:装饰器与原始对象实现相同接口,客户端无需区分处理的是原始对象还是装饰后的对象。多层嵌套
:支持多个装饰器层层嵌套,形成链式增强。
装饰器模式的模式结构
装饰器模式包含四个核心角色:
-
组件接口(Component)
声明被装饰对象和装饰器的共同接口。public interface Coffee { double getCost(); String getDescription(); }
-
具体组件(ConcreteComponent)
实现组件接口的基础对象。public class SimpleCoffee implements Coffee { @Override public double getCost() { return 2.0; // 基础咖啡价格 } @Override public String getDescription() { return "黑咖啡"; } }
-
装饰器抽象类(Decorator)
实现组件接口,并持有组件对象的引用。public abstract class CoffeeDecorator implements Coffee { protected Coffee decoratedCoffee; public CoffeeDecorator(Coffee coffee) { this.decoratedCoffee = coffee; } @Override public double getCost() { return decoratedCoffee.getCost(); } @Override public String getDescription() { return decoratedCoffee.getDescription(); } }
-
具体装饰器(ConcreteDecorator)
继承装饰器抽象类,添加具体增强功能。// 加牛奶装饰器 public class MilkDecorator extends CoffeeDecorator { public MilkDecorator(Coffee coffee) { super(coffee); } @Override public double getCost() { return super.getCost() + 0.5; // 增加牛奶费用 } @Override public String getDescription() { return super.getDescription() + ", 加牛奶"; } } // 加糖装饰器 public class SugarDecorator extends CoffeeDecorator { public SugarDecorator(Coffee coffee) { super(coffee); } @Override public double getCost() { return super.getCost() + 0.2; // 增加糖费用 } @Override public String getDescription() { return super.getDescription() + ", 加糖"; } }
-
代码运行
public class Client { public static void main(String[] args) { // 基础咖啡 Coffee coffee = new SimpleCoffee(); System.out.println("费用:" + coffee.getCost() + ",描述:" + coffee.getDescription()); // 加牛奶 Coffee milkCoffee = new MilkDecorator(coffee); System.out.println("费用:" + milkCoffee.getCost() + ",描述:" + milkCoffee.getDescription()); // 加牛奶和糖 Coffee sweetMilkCoffee = new SugarDecorator(milkCoffee); System.out.println("费用:" + sweetMilkCoffee.getCost() + ",描述:" + sweetMilkCoffee.getDescription()); } } // 输出: // 费用:2.0,描述:黑咖啡 // 费用:2.5,描述:黑咖啡, 加牛奶 // 费用:2.7,描述:黑咖啡, 加牛奶, 加糖
装饰器模式变体
-
接口替代抽象类
装饰器可以直接实现组件接口,无需抽象类(但抽象类可减少重复代码)。 -
动态撤销装饰
通过记录装饰器链,支持逐层移除装饰(需额外设计撤销逻辑)。
优缺点分析
优点
- 灵活扩展:动态添加功能,避免继承导致的类爆炸。
- 开闭原则:无需修改现有代码即可扩展新功能。
- 职责分离:每个装饰器专注单一功能,符合单一职责原则。
缺点
- 复杂度增加:多层装饰可能导致代码调试困难。
- 初始化冗余:创建装饰器链时代码可能冗长。
应用场景
适用场景
- 动态添加或撤销功能:如为对象添加日志、加密、缓存等职责。
- 避免类爆炸:当通过继承扩展功能会导致子类数量激增时。
- 不可变对象增强:无法修改现有类,但需扩展其行为。
实际应用
- Java I/O流:InputStream 和 BufferedInputStream、DataInputStream 等装饰器。
- GUI组件:为UI控件动态添加滚动条、边框等装饰。
- Web中间件:HTTP请求处理链中添加日志、鉴权装饰器。
与其他模式的关系
- 与代理模式:代理控制访问,装饰器增强功能。
- 与适配器模式:适配器改变接口,装饰器保持接口一致。
- 与责任链模式:装饰器链类似责任链,但目的不同(装饰器用于增强,责任链用于传递请求)。
总结
装饰器模式通过组合
和委托机制
,实现了功能的动态叠加
,是扩展对象行为的强大工具。在需要灵活、可逆地增强对象功能的场景中(如I/O流处理、UI组件定制),它能显著提升代码的可维护性和扩展性。