装饰者模式(Decorator Pattern) 属于结构型设计模式,通过将对象放入包含行为的特殊封装类中来动态添加新行为
+----------------+ +-----------------+
| Component |<|-------| Decorator |
|----------------| |-----------------|
| +operation() | | -component |
+----------------+ +-----------------+
^ ^
| |
+----------------+ +-----------------+
| ConcreteComponent | | ConcreteDecorator|
|----------------| |-----------------|
| +operation() | | +operation() |
+----------------+ +-----------------+
// 饮料抽象类(被装饰的组件)
public abstract class Beverage {
protected String description = "未知饮料";
public String getDescription() {
return description;
}
public abstract double cost();
}
// 具体组件:浓缩咖啡
public class Espresso extends Beverage {
public Espresso() {
description = "浓缩咖啡";
}
public double cost() {
return 1.99;
}
}
// 调料装饰器抽象类
public abstract class CondimentDecorator extends Beverage {
protected Beverage beverage; // 持有一个被装饰对象
public abstract String getDescription();
}
// 具体装饰器:牛奶
public class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", 牛奶";
}
public double cost() {
return beverage.cost() + 0.5;
}
}
// 具体装饰器:摩卡
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", 摩卡";
}
public double cost() {
return beverage.cost() + 0.7;
}
}
public class CoffeeShop {
public static void main(String[] args) {
// 点一杯双倍摩卡加奶的浓缩咖啡
Beverage order = new Espresso();
order = new Mocha(order); // 第一次装饰
order = new Mocha(order); // 第二次装饰
order = new Milk(order); // 第三次装饰
System.out.println(order.getDescription()
+ " 总价:$" + order.cost());
}
}
浓缩咖啡, 摩卡, 摩卡, 牛奶 总价:$3.89
优点 | 详细说明 | 生活案例类比 |
---|---|---|
灵活扩展 | 无需修改原有代码即可动态添加新功能 | 给手机加装手机壳不影响原有功能 |
避免类爆炸 | 替代多层继承结构(如咖啡×牛奶×糖 的组合只需3个类,继承方式需要6个子类) |
乐高积木式组合代替定制化零件 |
运行时组合 | 装饰顺序和组合方式可在运行时决定 | 穿衣时自由搭配外套、围巾顺序 |
符合开闭原则 | 新增装饰器不影响现有代码,扩展性好 | 新增咖啡配料无需修改咖啡机代码 |
// 扩展示例:新增一个装饰器
public class Sugar extends CondimentDecorator {
public Sugar(Beverage beverage) { this.beverage = beverage; }
public String getDescription() { return beverage.getDescription() + ", 糖"; }
public double cost() { return beverage.cost() + 0.3; }
}
// 使用新装饰器(无需修改原有代码)
Beverage coffee = new Espresso();
coffee = new Milk(coffee);
coffee = new Sugar(coffee); // 新增装饰器
缺点类型 | 问题表现 | 优化建议 |
---|---|---|
系统复杂度上升 | 大量小类增加维护成本 | 合并相似功能的装饰器 |
调试难度高 | 多层装饰导致调用链冗长 | 添加日志追踪装饰流程 |
设计门槛高 | 抽象层设计不当会导致结构混乱 | 提前定义清晰的装饰器规范 |
顺序依赖风险 | 装饰顺序不同可能引发结果差异 | 使用构建者模式控制装饰顺序 |
// 错误示例:装饰顺序影响结果
Beverage drink = new Coffee();
drink = new Milk(drink); // 先加奶
drink = new Sugar(drink); // 后加糖(最终甜度不同)
// 正确控制方式
Beverage drink = new Coffee();
drink = new SugarDecorator(drink); // 先加糖
drink = new MilkDecorator(drink); // 后加奶
InputStream in = new FileInputStream("data.txt");
in = new BufferedInputStream(in); // 装饰缓冲功能
in = new GZIPInputStream(in); // 装饰压缩功能
// 典型装饰链
Reader reader = new FileReader("data.txt");
reader = new BufferedReader(reader); // 添加缓冲功能
reader = new LineNumberReader(reader); // 添加行号统计
// 源码结构:
// FileReader(具体组件)
// BufferedReader(装饰器)
// LineNumberReader(装饰器的装饰器)
// 安全过滤器链装饰示例
HttpSecurity http = new HttpSecurity();
http.addFilter(new WebAsyncManagerIntegrationFilter())
.addFilter(new SecurityContextPersistenceFilter()) // 装饰安全上下文
.addFilter(new HeaderWriterFilter())
.addFilter(new CsrfFilter()); // 层层装饰安全功能
// 缓存装饰链示例
Cache cache = new PerpetualCache("default");
cache = new LruCache(cache); // 添加LRU淘汰策略
cache = new ScheduledCache(cache); // 添加定时刷新
cache = new SerializedCache(cache);// 添加序列化功能
Q1:装饰者模式 vs 继承?
关键区别:
Q2:如何控制装饰顺序?
Q3:装饰器会影响性能吗?