装饰器模式 (Decorator Pattern)
代码示例:
git clone https://gitee.com/qq1244811434/23DesignPatterns.git
优点
- 动态扩展对象功能,灵活性高
- 避免类爆炸,符合开闭原则
- 可组合多种装饰效果
缺点
- 增加系统复杂度
- 多层装饰时调试困难
特点
- 动态为对象添加新功能
- 装饰类与被装饰类实现同一接口
- 可多层嵌套装饰
应用场景
- 咖啡店点餐系统
- 文件读写装饰
- 日志记录装饰
测试
/**
* 演示装饰器模式
*/
@GetMapping("/decorator")
public Map<String, Object> demonstrateDecorator() {
Map<String, Object> result = new HashMap<>();
result.put("pattern", "装饰器模式");
result.put("description", "允许向一个现有的对象添加新的功能,同时又不改变其结构");
// 执行装饰器模式演示
decoratorPattern.demonstrateDecoratorPattern();
result.put("message", "装饰器模式演示完成,请查看控制台输出");
return result;
}
输出结果:
{
"pattern": "装饰器模式",
"description": "允许向一个现有的对象添加新的功能,同时又不改变其结构",
"message": "装饰器模式演示完成,请查看控制台输出"
}
控制台输出内容:
=== 咖啡装饰器模式演示 ===
订单: 基础咖啡
价格: 10.0元
制作基础咖啡
--- 添加装饰 ---
订单: 基础咖啡 + 糖
价格: 11.0元
制作基础咖啡
添加糖
订单: 基础咖啡 + 糖 + 牛奶
价格: 13.0元
制作基础咖啡
添加糖
添加牛奶
订单: 基础咖啡 + 糖 + 牛奶 + 冰块
价格: 13.5元
制作基础咖啡
添加糖
添加牛奶
添加冰块
完整代码
package com.example.patterns.decorator;
import org.springframework.stereotype.Component;
/**
* 装饰器模式演示
*
* 装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。
* 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
*
* 应用场景:
* - 咖啡店点餐系统
* - 文件读写装饰
* - 日志记录装饰
* - 权限验证装饰
*/
@Component
public class DecoratorPattern {
/**
* 抽象组件
* 组件接口 - 被装饰的对象
* 给对象动态的添加一些职责
*/
public interface Component {
void operation();
String getDescription();
double getCost();
}
/**
* 具体组件
* 实现了抽象组件接口,定义一个具体的对象
* 可以为此对象添加一些职责
*/
public static class SimpleCoffee implements Component {
@Override
public void operation() {
System.out.println("制作基础咖啡");
}
@Override
public String getDescription() {
return "基础咖啡";
}
@Override
public double getCost() {
return 10.0;
}
}
/**
* 抽象装饰器
* 装饰器抽象类
* 持有组件Component的引用,并定义了一个与抽象组件一致的接口
*/
public static abstract class CoffeeDecorator implements Component {
protected Component component;
public CoffeeDecorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
@Override
public String getDescription() {
return component.getDescription();
}
@Override
public double getCost() {
return component.getCost();
}
}
/**
* 具体装饰器
* 具体装饰器 - 加糖
*/
public static class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("添加糖");
}
@Override
public String getDescription() {
return super.getDescription() + " + 糖";
}
@Override
public double getCost() {
return super.getCost() + 1.0;
}
}
/**
* 具体装饰器 - 加奶
*/
public static class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("添加牛奶");
}
@Override
public String getDescription() {
return super.getDescription() + " + 牛奶";
}
@Override
public double getCost() {
return super.getCost() + 2.0;
}
}
/**
* 具体装饰器 - 加冰
*/
public static class IceDecorator extends CoffeeDecorator {
public IceDecorator(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
System.out.println("添加冰块");
}
@Override
public String getDescription() {
return super.getDescription() + " + 冰块";
}
@Override
public double getCost() {
return super.getCost() + 0.5;
}
}
/**
* 演示装饰器模式的使用
*/
public void demonstrateDecoratorPattern() {
System.out.println("=== 咖啡装饰器模式演示 ===");
// 创建基础咖啡
Component coffee = new SimpleCoffee();
System.out.println("订单: " + coffee.getDescription());
System.out.println("价格: " + coffee.getCost() + "元");
coffee.operation();
System.out.println("\n--- 添加装饰 ---");
// 添加糖
//在保持原有功能基础之上再添加加糖的功能即动态的为一个对象额外添加职能
//继承为静态,装饰为动态即在运行时可动态的用装饰器添加或删除某些功能,而继承是静态的
//可以任意组合多个装饰器
//符合开闭原则
coffee = new SugarDecorator(coffee);
System.out.println("订单: " + coffee.getDescription());
System.out.println("价格: " + coffee.getCost() + "元");
coffee.operation();
// 添加牛奶
// 不同功能划分在了不同的小类之中,每个小类只关注特定的一个功能
coffee = new MilkDecorator(coffee);
System.out.println("订单: " + coffee.getDescription());
System.out.println("价格: " + coffee.getCost() + "元");
coffee.operation();
// 添加冰块
coffee = new IceDecorator(coffee);
System.out.println("订单: " + coffee.getDescription());
System.out.println("价格: " + coffee.getCost() + "元");
coffee.operation();
}
}
UML:


被折叠的 条评论
为什么被折叠?



