java23种设计模式-装饰器模式

发布于:2025-02-27 ⋅ 阅读:(11) ⋅ 点赞:(0)

装饰者模式(Decorator Pattern)学习笔记

1. 模式定义

结构型设计模式,动态地为对象添加额外的职责。通过组合而非继承的方式扩展功能,提供比继承更灵活的替代方案。

2. 适用场景

✅ 需要动态/透明地给对象添加功能
✅ 需要撤销附加功能时
✅ 无法通过继承扩展功能(final类)
✅ 需要组合多个可选功能
✅ 避免"子类爆炸"问题

3. 模式结构

«interface»
Component
+operation()
ConcreteComponent
+operation()
Decorator
-component: Component
+operation()
ConcreteDecoratorA
+operation()
+addedBehavior()
ConcreteDecoratorB
+addedState
+operation()

4. 核心角色

角色 说明
Component 抽象组件,定义被装饰对象的接口
ConcreteComponent 具体组件,实现基本功能
Decorator 装饰者抽象类,持有组件引用并实现组件接口
ConcreteDecorator 具体装饰者,添加额外功能

5. 代码示例

5.1 咖啡加料示例

// 抽象组件
public interface Coffee {
    double getCost();
    String getDescription();
}

// 具体组件
public class SimpleCoffee implements Coffee {
    public double getCost() {
        return 2.0;
    }
    
    public String getDescription() {
        return "咖啡";
    }
}

// 抽象装饰者
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }
    
    public double getCost() {
        return decoratedCoffee.getCost();
    }
    
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}

// 具体装饰者
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    
    public double getCost() {
        return super.getCost() + 0.5;
    }
    
    public String getDescription() {
        return super.getDescription() + " + 牛奶";
    }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }
    
    public double getCost() {
        return super.getCost() + 0.2;
    }
    
    public String getDescription() {
        return super.getDescription() + " + 糖";
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        coffee = new MilkDecorator(coffee);
        coffee = new SugarDecorator(coffee);
        
        System.out.println("总价: $" + coffee.getCost());
        System.out.println("描述: " + coffee.getDescription());
        /* 输出:
           总价: $2.7
           描述: 咖啡 + 牛奶 + 糖 */
    }
}

6. 模式变种

  1. 透明装饰模式:保持接口完全一致,客户端无需知道装饰存在
  2. 半透明装饰模式:新增装饰者特有方法,客户端需要知道具体装饰类型
  3. 组合装饰器:通过链式调用实现多层装饰
Coffee coffee = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));

7. 优缺点分析

✔️ 优点

  • 扩展性比继承更好
  • 动态添加/撤销功能
  • 避免继承导致的类爆炸
  • 符合开闭原则

缺点

  • 产生大量小对象
  • 多层装饰增加调试难度
  • 装饰顺序可能影响结果
  • 需要管理装饰器组合关系

8. 相关模式对比

模式 目的 关键区别
适配器模式 接口转换 改变对象接口
代理模式 控制访问 保持接口相同
组合模式 树形结构处理 装饰者是被组合对象的包装
责任链模式 请求传递 装饰者可以终止处理过程

9. 实际应用案例

  • Java IO流体系:
    new BufferedInputStream(new FileInputStream("file.txt"));
    
  • Spring Security的过滤器链
  • Java GUI的组件装饰(Border/Scrollbar)
  • Servlet API的HttpServletRequestWrapper
  • Spring Web的HandlerInterceptor
  • MyBatis的Cache装饰器(FifoCache/LruCache)

10. 最佳实践建议

  1. 保持装饰接口透明:尽量不添加新方法,保持与组件接口一致
  2. 控制装饰层级:避免超过3层嵌套装饰
  3. 优先使用组合:通过组合不同装饰器实现功能叠加
  4. 注意装饰顺序:明确装饰器的应用顺序规则
  5. 使用工厂方法:封装复杂装饰组合的创建过程
  6. 实现撤销机制:提供removeDecorator()方法支持功能撤销

11. 扩展应用(增强HttpServletRequest)

public class LoggingHttpRequest extends HttpServletRequestWrapper {
    public LoggingHttpRequest(HttpServletRequest request) {
        super(request);
    }
    
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        System.out.println("获取参数: " + name + "=" + value);
        return value;
    }
    
    @Override
    public Part getPart(String name) throws IOException, ServletException {
        Part part = super.getPart(name);
        System.out.println("上传文件: " + name + " size=" + part.getSize());
        return part;
    }
}

// 在Filter中使用
public class LoggingFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        HttpServletRequest wrappedRequest = new LoggingHttpRequest((HttpServletRequest) request);
        chain.doFilter(wrappedRequest, response);
    }
}

🎁 设计原则体现

  1. 开闭原则(OCP):不修改原有类即可扩展新功能
  2. 组合优于继承(Composite Reuse Principle):使用对象组合代替类继承
  3. 单一职责原则(SRP):每个装饰者只关注单一功能增强

通过装饰者模式,可以实现灵活的功能扩展,特别适合需要动态组合多种可选功能的场景。该模式在框架设计和基础库开发中应用广泛,是处理功能叠加问题的经典解决方案。