23种设计模式之【装饰器模式】-核心原理与 Java实践
23种设计模式之【装饰器模式】-核心原理与 Java实践
- 装饰器模式(Decorator Pattern)
- 核心原理
- Java 实践示例
- 装饰器模式的特点
- 装饰器模式的应用场景
装饰器模式(Decorator Pattern)
装饰器模式是 23 种设计模式中的一种结构型模式,其核心思想是动态地给一个对象添加额外的职责,就像在墙上刷油漆一样,不改变原有对象的结构,但能增强其功能。这种模式相比继承更灵活,可以在运行时动态扩展对象功能,且支持多层嵌套装饰。
核心原理
抽象组件(Component):
定义被装饰对象和装饰器的共同接口
是所有具体组件和装饰器的超类型
具体组件(ConcreteComponent):
实现抽象组件接口,是被装饰的原始对象
包含核心业务逻辑
抽象装饰器(Decorator):
实现抽象组件接口,持有一个抽象组件的引用
定义所有具体装饰器的公共行为
具体装饰器(ConcreteDecorator):
继承抽象装饰器,实现具体的增强功能
在调用被装饰对象的方法前后添加额外操作
装饰器模式的核心是 “组合替代继承”,通过嵌套组合多个装饰器,实现对对象功能的灵活扩展。
Java 实践示例
以 “咖啡订单系统” 为例实现装饰器模式:
基础咖啡(如美式咖啡)是被装饰的原始对象
可以添加各种配料(牛奶、糖、巧克力)作为装饰器,动态增强咖啡的功能
package com.example.demo;public class DecoratorPattern {public static void main(String[] args) {// 点一杯基础美式咖啡Coffee coffee = new Americano();System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");// 加牛奶coffee = new MilkDecorator(coffee);System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");// 再加糖coffee = new SugarDecorator(coffee);System.out.println(coffee.getDescription() + ",价格:" + coffee.cost() + "元");// 点一杯拿铁,加巧克力Coffee latte = new Latte();latte = new ChocolateDecorator(latte);System.out.println(latte.getDescription() + ",价格:" + latte.cost() + "元");}// 抽象组件:咖啡接口public interface Coffee {// 获取咖啡描述String getDescription();// 计算价格double cost();}// 具体组件:美式咖啡public static class Americano implements Coffee {@Overridepublic String getDescription() {return "美式咖啡";}@Overridepublic double cost() {return 25.0;}}// 具体组件:拿铁咖啡public static class Latte implements Coffee {@Overridepublic String getDescription() {return "拿铁咖啡";}@Overridepublic double cost() {return 32.0;}}// 抽象装饰器:咖啡装饰器public abstract static class CoffeeDecorator implements Coffee {protected Coffee coffee; // 持有被装饰的咖啡对象// 通过构造函数注入被装饰对象public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic String getDescription() {return coffee.getDescription();}@Overridepublic double cost() {return coffee.cost();}}// 具体装饰器:牛奶public static class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return coffee.getDescription() + " + 牛奶";}@Overridepublic double cost() {return coffee.cost() + 5.0; // 加牛奶增加5元}}// 具体装饰器:糖public static class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return coffee.getDescription() + " + 糖";}@Overridepublic double cost() {return coffee.cost() + 2.0; // 加糖增加2元}}// 具体装饰器:巧克力public static class ChocolateDecorator extends CoffeeDecorator {public ChocolateDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return coffee.getDescription() + " + 巧克力";}@Overridepublic double cost() {return coffee.cost() + 8.0; // 加巧克力增加8元}}
}
美式咖啡,价格:25.0元
美式咖啡 + 牛奶,价格:30.0元
美式咖啡 + 牛奶 + 糖,价格:32.0元
拿铁咖啡 + 巧克力,价格:40.0元
装饰器模式的特点
优点:
灵活性高:可以动态地给对象添加或移除功能,比继承更灵活
组合性强:支持多层装饰,通过不同组合实现多样化功能
遵循开闭原则:新增装饰器无需修改原有代码
单一职责:每个装饰器只负责一种增强功能,职责清晰
缺点:
复杂度增加:多层装饰可能导致系统中出现大量小对象
调试困难:调用链较长时,排查问题需要逐层分析
与继承的区别:
继承:编译期静态扩展,功能固定,不灵活
装饰器:运行时动态扩展,可灵活组合,功能可变
装饰器模式的应用场景
IO 流(Java 经典应用):
InputStream/OutputStream、Reader/Writer体系中大量使用装饰器
例如:BufferedInputStream装饰FileInputStream增加缓冲功能,DataInputStream增加数据类型处理功能
// Java IO中的装饰器模式
InputStream is = new FileInputStream("data.txt");
InputStream bis = new BufferedInputStream(is); // 增加缓冲功能
DataInputStream dis = new DataInputStream(bis); // 增加数据类型处理功能
GUI 组件:
图形界面中给组件添加边框、滚动条等装饰
例如:JScrollPane装饰JTextArea添加滚动功能
日志增强:
给方法调用添加日志记录、性能监控等功能
例如:在原有业务方法前后添加日志打印装饰器
权限控制:
动态为不同用户添加不同的操作权限
例如:普通用户→VIP 用户→管理员的权限装饰链
装饰器模式是扩展对象功能的重要方式,尤其适合需要灵活组合多种功能的场景。Java IO 流是装饰器模式的典范,通过嵌套不同的装饰器,实现了丰富的 IO 操作功能