设计模式-装饰器模式详解

装饰器模式详解

1. 装饰器模式简介

1.1 定义

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。装饰器模式通过创建一个包装对象来动态地给一个对象添加一些额外的职责。

1.2 核心思想

  • 动态扩展:在运行时动态地给对象添加功能
  • 透明包装:装饰器与被装饰的对象具有相同的接口
  • 组合优于继承:通过组合的方式实现功能扩展,避免继承的复杂性

1.3 模式结构

contains <<interface>> Component +operation() ConcreteComponent +operation() Decorator -component: Component +Decorator(Component) +operation() ConcreteDecoratorA +operation() +addedBehavior() ConcreteDecoratorB +operation() +addedBehavior()

结构说明:

  • Component(抽象组件):定义对象的接口,可以给这些对象动态地添加职责
  • ConcreteComponent(具体组件):定义具体的对象,也可以给这个对象添加一些职责
  • Decorator(抽象装饰器):维护一个指向Component对象的引用,并定义一个与Component接口一致的接口
  • ConcreteDecorator(具体装饰器):向组件添加职责

1.4 工作流程

客户端 装饰器 被装饰对象 调用operation() 执行装饰逻辑 调用被装饰对象的operation() 返回结果 执行后续装饰逻辑 返回最终结果 客户端 装饰器 被装饰对象

2. 应用场景

2.1 典型应用场景

  1. 功能增强:在不修改原有类的基础上,动态地添加功能
  2. 职责分离:将不同的职责分离到不同的装饰器中
  3. 替代继承:当使用继承会导致类爆炸时,使用装饰器模式
  4. 运行时扩展:需要在运行时决定如何组合功能

2.2 实际应用示例

2.2.1 Java I/O流装饰器示例
java 复制代码
// 基础组件接口
public interface DataSource {
    void writeData(String data);
    String readData();
}

// 具体组件
public class FileDataSource implements DataSource {
    private String filename;
  
    public FileDataSource(String filename) {
        this.filename = filename;
    }
  
    @Override
    public void writeData(String data) {
        System.out.println("写入文件 " + filename + ": " + data);
    }
  
    @Override
    public String readData() {
        return "从文件 " + filename + " 读取数据";
    }
}

// 抽象装饰器
public abstract class DataSourceDecorator implements DataSource {
    protected DataSource wrappee;
  
    public DataSourceDecorator(DataSource source) {
        this.wrappee = source;
    }
  
    @Override
    public void writeData(String data) {
        wrappee.writeData(data);
    }
  
    @Override
    public String readData() {
        return wrappee.readData();
    }
}

// 加密装饰器
public class EncryptionDecorator extends DataSourceDecorator {
    public EncryptionDecorator(DataSource source) {
        super(source);
    }
  
    @Override
    public void writeData(String data) {
        String encryptedData = encrypt(data);
        super.writeData(encryptedData);
    }
  
    @Override
    public String readData() {
        String encryptedData = super.readData();
        return decrypt(encryptedData);
    }
  
    private String encrypt(String data) {
        return "加密(" + data + ")";
    }
  
    private String decrypt(String data) {
        return data.replace("加密(", "").replace(")", "");
    }
}

// 压缩装饰器
public class CompressionDecorator extends DataSourceDecorator {
    public CompressionDecorator(DataSource source) {
        super(source);
    }
  
    @Override
    public void writeData(String data) {
        String compressedData = compress(data);
        super.writeData(compressedData);
    }
  
    @Override
    public String readData() {
        String compressedData = super.readData();
        return decompress(compressedData);
    }
  
    private String compress(String data) {
        return "压缩(" + data + ")";
    }
  
    private String decompress(String data) {
        return data.replace("压缩(", "").replace(")", "");
    }
}

// 使用示例
public class DecoratorDemo {
    public static void main(String[] args) {
        // 基础文件数据源
        DataSource source = new FileDataSource("data.txt");
      
        // 添加加密功能
        DataSource encryptedSource = new EncryptionDecorator(source);
      
        // 添加压缩功能
        DataSource compressedSource = new CompressionDecorator(encryptedSource);
      
        // 使用装饰后的数据源
        compressedSource.writeData("Hello World");
        String data = compressedSource.readData();
        System.out.println("读取数据: " + data);
    }
}
2.2.2 缓存装饰器示例
java 复制代码
// 服务接口
public interface UserService {
    User getUserById(Long id);
    void saveUser(User user);
}

// 具体服务实现
@Service
public class UserServiceImpl implements UserService {
    @Override
    public User getUserById(Long id) {
        System.out.println("从数据库查询用户: " + id);
        // 模拟数据库查询
        return new User(id, "用户" + id);
    }
  
    @Override
    public void saveUser(User user) {
        System.out.println("保存用户到数据库: " + user);
    }
}

// 缓存装饰器
@Component
public class CachedUserService implements UserService {
    private final UserService userService;
    private final Map<Long, User> cache = new ConcurrentHashMap<>();
  
    public CachedUserService(UserService userService) {
        this.userService = userService;
    }
  
    @Override
    public User getUserById(Long id) {
        // 先从缓存获取
        User cachedUser = cache.get(id);
        if (cachedUser != null) {
            System.out.println("从缓存获取用户: " + id);
            return cachedUser;
        }
      
        // 缓存未命中,从数据库查询
        User user = userService.getUserById(id);
        cache.put(id, user);
        return user;
    }
  
    @Override
    public void saveUser(User user) {
        userService.saveUser(user);
        // 更新缓存
        cache.put(user.getId(), user);
    }
}

// 日志装饰器
@Component
public class LoggedUserService implements UserService {
    private final UserService userService;
    private static final Logger logger = LoggerFactory.getLogger(LoggedUserService.class);
  
    public LoggedUserService(UserService userService) {
        this.userService = userService;
    }
  
    @Override
    public User getUserById(Long id) {
        logger.info("开始查询用户: {}", id);
        long startTime = System.currentTimeMillis();
      
        try {
            User user = userService.getUserById(id);
            long endTime = System.currentTimeMillis();
            logger.info("查询用户完成: {}, 耗时: {}ms", user, endTime - startTime);
            return user;
        } catch (Exception e) {
            logger.error("查询用户失败: {}", id, e);
            throw e;
        }
    }
  
    @Override
    public void saveUser(User user) {
        logger.info("开始保存用户: {}", user);
        userService.saveUser(user);
        logger.info("保存用户完成: {}", user);
    }
}

// 组合使用
@Configuration
public class ServiceConfig {
    @Bean
    public UserService userService() {
        UserService baseService = new UserServiceImpl();
        UserService cachedService = new CachedUserService(baseService);
        return new LoggedUserService(cachedService);
    }
}
2.2.3 Web中间件装饰器示例
java 复制代码
// 请求处理器接口
public interface RequestHandler {
    void handle(HttpServletRequest request, HttpServletResponse response);
}

// 基础处理器
@Component
public class BasicRequestHandler implements RequestHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("处理业务逻辑");
    }
}

// 认证装饰器
@Component
public class AuthenticationDecorator implements RequestHandler {
    private final RequestHandler handler;
  
    public AuthenticationDecorator(RequestHandler handler) {
        this.handler = handler;
    }
  
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response) {
        if (isAuthenticated(request)) {
            handler.handle(request, response);
        } else {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
  
    private boolean isAuthenticated(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        return token != null && token.startsWith("Bearer ");
    }
}

// 日志装饰器
@Component
public class LoggingDecorator implements RequestHandler {
    private final RequestHandler handler;
    private static final Logger logger = LoggerFactory.getLogger(LoggingDecorator.class);
  
    public LoggingDecorator(RequestHandler handler) {
        this.handler = handler;
    }
  
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response) {
        logger.info("请求开始: {} {}", request.getMethod(), request.getRequestURI());
        long startTime = System.currentTimeMillis();
      
        try {
            handler.handle(request, response);
            long endTime = System.currentTimeMillis();
            logger.info("请求完成: 状态码={}, 耗时={}ms", response.getStatus(), endTime - startTime);
        } catch (Exception e) {
            logger.error("请求处理失败", e);
            throw e;
        }
    }
}

// 限流装饰器
@Component
public class RateLimitDecorator implements RequestHandler {
    private final RequestHandler handler;
    private final Map<String, AtomicInteger> requestCounts = new ConcurrentHashMap<>();
    private final int maxRequestsPerMinute = 100;
  
    public RateLimitDecorator(RequestHandler handler) {
        this.handler = handler;
    }
  
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response) {
        String clientIp = getClientIp(request);
        AtomicInteger count = requestCounts.computeIfAbsent(clientIp, k -> new AtomicInteger(0));
      
        if (count.incrementAndGet() > maxRequestsPerMinute) {
            response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
            return;
        }
      
        handler.handle(request, response);
    }
  
    private String getClientIp(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0];
        }
        return request.getRemoteAddr();
    }
}

// 配置组合
@Configuration
public class HandlerConfig {
    @Bean
    public RequestHandler requestHandler() {
        RequestHandler baseHandler = new BasicRequestHandler();
        RequestHandler loggedHandler = new LoggingDecorator(baseHandler);
        RequestHandler rateLimitedHandler = new RateLimitDecorator(loggedHandler);
        return new AuthenticationDecorator(rateLimitedHandler);
    }
}

3. 重难点分析

3.1 重点

3.1.1 接口一致性

理论:装饰器必须与被装饰对象实现相同的接口

案例:接口不一致导致的问题

java 复制代码
// ❌ 错误示例:接口不一致
public interface DataProcessor {
    String process(String data);
}

public class BasicProcessor implements DataProcessor {
    @Override
    public String process(String data) {
        return "处理: " + data;
    }
}

// 错误的装饰器 - 接口不匹配
public class WrongDecorator {
    private DataProcessor processor;
  
    public WrongDecorator(DataProcessor processor) {
        this.processor = processor;
    }
  
    // 缺少process方法,无法作为DataProcessor使用
    public String enhancedProcess(String data) {
        return "增强处理: " + processor.process(data);
    }
}

// ✅ 正确示例:接口一致
public class CorrectDecorator implements DataProcessor {
    private DataProcessor processor;
  
    public CorrectDecorator(DataProcessor processor) {
        this.processor = processor;
    }
  
    @Override
    public String process(String data) {
        return "增强处理: " + processor.process(data);
    }
}
3.1.2 组合关系

理论:装饰器持有被装饰对象的引用

案例:组合关系的正确实现

java 复制代码
// 基础服务接口
public interface PaymentService {
    void pay(BigDecimal amount);
    void refund(BigDecimal amount);
}

// 基础实现
public class BasicPaymentService implements PaymentService {
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("支付: " + amount);
    }
  
    @Override
    public void refund(BigDecimal amount) {
        System.out.println("退款: " + amount);
    }
}

// 正确的装饰器实现
public class LoggingPaymentDecorator implements PaymentService {
    private final PaymentService paymentService; // 组合关系
    private final Logger logger = LoggerFactory.getLogger(LoggingPaymentDecorator.class);
  
    public LoggingPaymentDecorator(PaymentService paymentService) {
        this.paymentService = paymentService; // 持有被装饰对象的引用
    }
  
    @Override
    public void pay(BigDecimal amount) {
        logger.info("支付开始: {}", amount);
        paymentService.pay(amount); // 委托给被装饰对象
        logger.info("支付完成: {}", amount);
    }
  
    @Override
    public void refund(BigDecimal amount) {
        logger.info("退款开始: {}", amount);
        paymentService.refund(amount);
        logger.info("退款完成: {}", amount);
    }
}
3.1.3 透明性

理论:客户端代码无需知道是否使用了装饰器

案例:透明性演示

java 复制代码
public class PaymentClient {
    public static void main(String[] args) {
        // 客户端代码完全一样,无论是否使用装饰器
        PaymentService service = createPaymentService();
      
        // 客户端无需知道service是否被装饰
        service.pay(new BigDecimal("100.00"));
        service.refund(new BigDecimal("50.00"));
    }
  
    private static PaymentService createPaymentService() {
        PaymentService baseService = new BasicPaymentService();
      
        // 可以随时添加或移除装饰器,客户端代码不变
        return new LoggingPaymentDecorator(baseService);
        // 或者:return new ValidationPaymentDecorator(baseService);
        // 或者:return baseService; // 不使用装饰器
    }
}
3.1.4 灵活性

理论:可以任意组合多个装饰器

案例:装饰器组合的灵活性

java 复制代码
// 验证装饰器
public class ValidationPaymentDecorator implements PaymentService {
    private final PaymentService paymentService;
  
    public ValidationPaymentDecorator(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("支付金额必须大于0");
        }
        paymentService.pay(amount);
    }
  
    @Override
    public void refund(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("退款金额必须大于0");
        }
        paymentService.refund(amount);
    }
}

// 监控装饰器
public class MonitoringPaymentDecorator implements PaymentService {
    private final PaymentService paymentService;
    private final MeterRegistry meterRegistry;
  
    public MonitoringPaymentDecorator(PaymentService paymentService, MeterRegistry meterRegistry) {
        this.paymentService = paymentService;
        this.meterRegistry = meterRegistry;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        Timer.Sample sample = Timer.start(meterRegistry);
        try {
            paymentService.pay(amount);
            meterRegistry.counter("payment.success").increment();
        } catch (Exception e) {
            meterRegistry.counter("payment.error").increment();
            throw e;
        } finally {
            sample.stop(Timer.builder("payment.duration").register(meterRegistry));
        }
    }
  
    @Override
    public void refund(BigDecimal amount) {
        // 类似的监控逻辑
        paymentService.refund(amount);
    }
}

// 灵活的组合方式
public class PaymentServiceFactory {
    public static PaymentService createService(boolean enableLogging, boolean enableValidation, boolean enableMonitoring) {
        PaymentService service = new BasicPaymentService();
      
        if (enableLogging) {
            service = new LoggingPaymentDecorator(service);
        }
      
        if (enableValidation) {
            service = new ValidationPaymentDecorator(service);
        }
      
        if (enableMonitoring) {
            service = new MonitoringPaymentDecorator(service, meterRegistry);
        }
      
        return service;
    }
}

3.2 难点

3.2.1 设计复杂性

理论:需要设计合理的抽象层

案例:设计复杂性的挑战

java 复制代码
// ❌ 设计过于复杂 - 抽象层过多
public abstract class AbstractPaymentDecorator implements PaymentService {
    protected PaymentService paymentService;
  
    public AbstractPaymentDecorator(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

public abstract class LoggingDecorator extends AbstractPaymentDecorator {
    protected Logger logger;
  
    public LoggingDecorator(PaymentService paymentService) {
        super(paymentService);
        this.logger = LoggerFactory.getLogger(getClass());
    }
}

public abstract class ValidationDecorator extends AbstractPaymentDecorator {
    protected void validateAmount(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("金额必须大于0");
        }
    }
}

// 具体实现变得复杂
public class LoggingValidationPaymentDecorator extends ValidationDecorator {
    private Logger logger = LoggerFactory.getLogger(LoggingValidationPaymentDecorator.class);
  
    public LoggingValidationPaymentDecorator(PaymentService paymentService) {
        super(paymentService);
    }
  
    @Override
    public void pay(BigDecimal amount) {
        logger.info("支付开始");
        validateAmount(amount);
        paymentService.pay(amount);
        logger.info("支付完成");
    }
  
    @Override
    public void refund(BigDecimal amount) {
        logger.info("退款开始");
        validateAmount(amount);
        paymentService.refund(amount);
        logger.info("退款完成");
    }
}

// ✅ 简化设计 - 职责单一
public class SimpleLoggingDecorator implements PaymentService {
    private final PaymentService paymentService;
    private final Logger logger = LoggerFactory.getLogger(SimpleLoggingDecorator.class);
  
    public SimpleLoggingDecorator(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        logger.info("支付: {}", amount);
        paymentService.pay(amount);
    }
  
    @Override
    public void refund(BigDecimal amount) {
        logger.info("退款: {}", amount);
        paymentService.refund(amount);
    }
}
3.2.2 调试困难

理论:多层装饰器可能导致调试复杂

案例:调试困难的场景

java 复制代码
// 多层装饰器链
public class DebuggingExample {
    public static void main(String[] args) {
        PaymentService service = new BasicPaymentService();
        service = new LoggingDecorator(service);
        service = new ValidationDecorator(service);
        service = new MonitoringDecorator(service);
        service = new RetryDecorator(service);
        service = new CircuitBreakerDecorator(service);
      
        // 当出现异常时,很难定位是哪个装饰器的问题
        try {
            service.pay(new BigDecimal("-100")); // 负数金额
        } catch (Exception e) {
            // 异常堆栈可能很长,难以定位问题
            e.printStackTrace();
        }
    }
}

// 解决方案:添加调试信息
public class DebugLoggingDecorator implements PaymentService {
    private final PaymentService paymentService;
    private final Logger logger = LoggerFactory.getLogger(DebugLoggingDecorator.class);
    private final String decoratorName;
  
    public DebugLoggingDecorator(PaymentService paymentService, String decoratorName) {
        this.paymentService = paymentService;
        this.decoratorName = decoratorName;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        logger.debug("{} - 支付开始: {}", decoratorName, amount);
        try {
            paymentService.pay(amount);
            logger.debug("{} - 支付成功: {}", decoratorName, amount);
        } catch (Exception e) {
            logger.error("{} - 支付失败: {}, 错误: {}", decoratorName, amount, e.getMessage());
            throw e;
        }
    }
  
    @Override
    public void refund(BigDecimal amount) {
        // 类似的调试逻辑
        paymentService.refund(amount);
    }
}
3.2.3 性能考虑

理论:多层装饰器可能影响性能

案例:性能问题分析

java 复制代码
// 性能测试装饰器
public class PerformanceTestDecorator implements PaymentService {
    private final PaymentService paymentService;
    private final String decoratorName;
  
    public PerformanceTestDecorator(PaymentService paymentService, String decoratorName) {
        this.paymentService = paymentService;
        this.decoratorName = decoratorName;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        long startTime = System.nanoTime();
        try {
            paymentService.pay(amount);
        } finally {
            long endTime = System.nanoTime();
            long duration = endTime - startTime;
            System.out.println(decoratorName + " 耗时: " + duration + " 纳秒");
        }
    }
  
    @Override
    public void refund(BigDecimal amount) {
        paymentService.refund(amount);
    }
}

// 性能测试
public class PerformanceTest {
    public static void main(String[] args) {
        PaymentService service = new BasicPaymentService();
      
        // 测试不同装饰器层数的性能
        for (int i = 1; i <= 10; i++) {
            service = new PerformanceTestDecorator(service, "装饰器" + i);
        }
      
        // 执行测试
        long startTime = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            service.pay(new BigDecimal("100"));
        }
        long endTime = System.nanoTime();
      
        System.out.println("总耗时: " + (endTime - startTime) + " 纳秒");
    }
}

// 性能优化:减少不必要的装饰器
public class OptimizedPaymentService implements PaymentService {
    private final PaymentService paymentService;
    private final boolean enableLogging;
    private final boolean enableValidation;
    private final Logger logger = LoggerFactory.getLogger(OptimizedPaymentService.class);
  
    public OptimizedPaymentService(PaymentService paymentService, boolean enableLogging, boolean enableValidation) {
        this.paymentService = paymentService;
        this.enableLogging = enableLogging;
        this.enableValidation = enableValidation;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        if (enableValidation && amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("金额必须大于0");
        }
      
        if (enableLogging) {
            logger.info("支付: {}", amount);
        }
      
        paymentService.pay(amount);
    }
  
    @Override
    public void refund(BigDecimal amount) {
        if (enableValidation && amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("金额必须大于0");
        }
      
        if (enableLogging) {
            logger.info("退款: {}", amount);
        }
      
        paymentService.refund(amount);
    }
}
3.2.4 类型安全

理论:需要确保类型安全

案例:类型安全问题

java 复制代码
// ❌ 类型不安全的装饰器
public class UnsafeDecorator {
    private Object target; // 使用Object类型,不安全
  
    public UnsafeDecorator(Object target) {
        this.target = target;
    }
  
    public Object process(Object data) {
        // 需要强制类型转换,可能抛出ClassCastException
        if (target instanceof StringProcessor) {
            return ((StringProcessor) target).process((String) data);
        }
        return data;
    }
}

// ✅ 类型安全的装饰器
public class SafeStringDecorator implements StringProcessor {
    private final StringProcessor stringProcessor; // 使用具体类型
  
    public SafeStringDecorator(StringProcessor stringProcessor) {
        this.stringProcessor = stringProcessor;
    }
  
    @Override
    public String process(String data) {
        // 类型安全,无需强制转换
        return "装饰: " + stringProcessor.process(data);
    }
}

// 泛型装饰器,提供更好的类型安全
public class GenericDecorator<T> implements Processor<T> {
    private final Processor<T> processor;
  
    public GenericDecorator(Processor<T> processor) {
        this.processor = processor;
    }
  
    @Override
    public T process(T data) {
        return processor.process(data);
    }
}

3.3 常见陷阱

3.3.1 装饰器链过长导致性能问题

案例:链过长的问题

java 复制代码
// ❌ 装饰器链过长
public class LongChainExample {
    public static void main(String[] args) {
        PaymentService service = new BasicPaymentService();
      
        // 创建过长的装饰器链
        for (int i = 0; i < 100; i++) {
            service = new LoggingDecorator(service);
        }
      
        // 性能问题:每次调用都要经过100层装饰器
        service.pay(new BigDecimal("100"));
    }
}

// ✅ 解决方案:合并装饰器
public class CombinedDecorator implements PaymentService {
    private final PaymentService paymentService;
    private final Logger logger = LoggerFactory.getLogger(CombinedDecorator.class);
    private final boolean enableValidation;
    private final boolean enableMonitoring;
  
    public CombinedDecorator(PaymentService paymentService, boolean enableValidation, boolean enableMonitoring) {
        this.paymentService = paymentService;
        this.enableValidation = enableValidation;
        this.enableMonitoring = enableMonitoring;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        if (enableValidation && amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("金额必须大于0");
        }
      
        if (enableMonitoring) {
            logger.info("支付开始: {}", amount);
        }
      
        paymentService.pay(amount);
      
        if (enableMonitoring) {
            logger.info("支付完成: {}", amount);
        }
    }
  
    @Override
    public void refund(BigDecimal amount) {
        // 类似的合并逻辑
        paymentService.refund(amount);
    }
}
3.3.2 忘记调用被装饰对象的方法

案例:忘记委托的问题

java 复制代码
// ❌ 忘记调用被装饰对象的方法
public class ForgotDelegateDecorator implements PaymentService {
    private final PaymentService paymentService;
  
    public ForgotDelegateDecorator(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("支付日志: " + amount);
        // 忘记调用 paymentService.pay(amount);
        // 导致实际支付逻辑没有执行
    }
  
    @Override
    public void refund(BigDecimal amount) {
        System.out.println("退款日志: " + amount);
        // 忘记调用 paymentService.refund(amount);
    }
}

// ✅ 正确的实现
public class CorrectDelegateDecorator implements PaymentService {
    private final PaymentService paymentService;
  
    public CorrectDelegateDecorator(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
  
    @Override
    public void pay(BigDecimal amount) {
        System.out.println("支付日志: " + amount);
        paymentService.pay(amount); // 记得委托给被装饰对象
    }
  
    @Override
    public void refund(BigDecimal amount) {
        System.out.println("退款日志: " + amount);
        paymentService.refund(amount); // 记得委托给被装饰对象
    }
}
3.3.3 装饰器之间的依赖关系处理不当

案例:依赖关系问题

java 复制代码
// ❌ 装饰器依赖关系处理不当
public class DependencyProblemExample {
    public static void main(String[] args) {
        PaymentService service = new BasicPaymentService();
      
        // 错误的顺序:验证在日志之前,但验证失败时日志不会记录
        service = new ValidationDecorator(service);
        service = new LoggingDecorator(service);
      
        try {
            service.pay(new BigDecimal("-100")); // 验证失败,日志不会记录
        } catch (Exception e) {
            // 日志装饰器没有机会记录异常
        }
    }
}

// ✅ 正确的依赖关系处理
public class CorrectDependencyExample {
    public static void main(String[] args) {
        PaymentService service = new BasicPaymentService();
      
        // 正确的顺序:日志在验证之前,可以记录所有操作
        service = new LoggingDecorator(service);
        service = new ValidationDecorator(service);
      
        try {
            service.pay(new BigDecimal("-100")); // 验证失败,但日志会记录
        } catch (Exception e) {
            // 日志装饰器已经记录了异常
        }
    }
}

// 或者使用装饰器工厂来管理依赖关系
public class DecoratorFactory {
    public static PaymentService createService(boolean enableLogging, boolean enableValidation) {
        PaymentService service = new BasicPaymentService();
      
        // 按照正确的依赖顺序添加装饰器
        if (enableLogging) {
            service = new LoggingDecorator(service);
        }
      
        if (enableValidation) {
            service = new ValidationDecorator(service);
        }
      
        return service;
    }
}

4. 在Spring中的应用

4.1 Spring AOP中的装饰器模式

Spring AOP本质上就是装饰器模式的实现,通过代理对象来增强目标对象的功能。

java 复制代码
// 目标接口
public interface UserService {
    void saveUser(User user);
}

// 目标实现
@Service
public class UserServiceImpl implements UserService {
    @Override
    public void saveUser(User user) {
        // 保存用户逻辑
    }
}

// 装饰器(AOP切面)
@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.example.service.UserService.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("方法执行前");
        Object result = joinPoint.proceed();
        System.out.println("方法执行后");
        return result;
    }
}

4.2 Spring MVC中的装饰器模式

  • HandlerInterceptor:请求拦截器
  • Filter:过滤器链
  • ViewResolver:视图解析器链

4.3 Spring Security中的装饰器模式

  • AuthenticationProvider:认证提供者链
  • AccessDecisionVoter:访问决策投票器链

5. 相关源码解读

5.1 Java I/O流中的装饰器模式

java 复制代码
// 抽象组件
public abstract class InputStream {
    public abstract int read() throws IOException;
    // 其他方法...
}

// 具体组件
public class FileInputStream extends InputStream {
    @Override
    public int read() throws IOException {
        // 从文件读取数据
    }
}

// 抽象装饰器
public class FilterInputStream extends InputStream {
    protected volatile InputStream in;
  
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
  
    @Override
    public int read() throws IOException {
        return in.read();
    }
}

// 具体装饰器
public class BufferedInputStream extends FilterInputStream {
    private byte[] buf;
    private int count;
    private int pos;
  
    public BufferedInputStream(InputStream in) {
        super(in);
        buf = new byte[8192];
    }
  
    @Override
    public int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return buf[pos++] & 0xff;
    }
}

5.2 Spring AOP源码分析

java 复制代码
// 核心接口
public interface AopProxy {
    Object getProxy();
    Object getProxy(ClassLoader classLoader);
}

// JDK动态代理实现
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
    private final AdvisedSupport advised;
  
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 获取拦截器链
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      
        if (chain.isEmpty()) {
            // 直接调用目标方法
            return AopUtils.invokeJoinpointUsingReflection(target, method, args);
        } else {
            // 创建方法调用链
            ReflectiveMethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            return invocation.proceed();
        }
    }
}

6. 面试高频点

6.1 基础概念

  • Q: 装饰器模式与代理模式的区别?
  • A: 装饰器模式关注功能的增强,代理模式关注访问控制

6.2 设计原则

  • Q: 装饰器模式体现了哪些设计原则?
  • A: 开闭原则、单一职责原则、组合优于继承

6.3 实际应用

  • Q: 在Spring中如何实现装饰器模式?
  • A: 通过AOP、拦截器、过滤器等机制

6.4 性能考虑

  • Q: 装饰器模式对性能有什么影响?
  • A: 多层装饰器会增加方法调用栈深度,需要权衡功能与性能

6.5 代码实现

  • Q: 如何实现一个缓存装饰器?
  • A: 实现目标接口,持有目标对象引用,添加缓存逻辑

7. 学习途径

7.1 理论学习

  1. 设计模式书籍

    • 《设计模式:可复用面向对象软件的基础》
    • 《Head First设计模式》
    • 《Java设计模式》
  2. 在线资源

    • 菜鸟教程设计模式章节
    • 慕课网设计模式课程
    • B站相关视频教程

7.2 实践学习

  1. 代码实现

    • 实现简单的装饰器模式示例
    • 分析Java I/O流的装饰器实现
    • 研究Spring AOP的装饰器应用
  2. 项目应用

    • 在项目中应用装饰器模式
    • 实现日志装饰器
    • 实现缓存装饰器

7.3 源码学习

  1. Java源码

    • java.io包中的装饰器实现
    • java.util.Collections中的装饰器方法
  2. Spring源码

    • AOP相关源码
    • MVC拦截器源码
    • Security过滤器源码

7.4 进阶学习

  1. 框架应用

    • Spring Boot中的装饰器应用
    • MyBatis中的装饰器模式
    • Dubbo中的装饰器应用
  2. 性能优化

    • 装饰器模式的性能优化
    • 代理对象的缓存策略
    • 方法调用的性能分析

8. 总结

装饰器模式是一种非常实用的设计模式,它通过组合的方式实现了功能的动态扩展,避免了继承的复杂性。在Spring框架中,装饰器模式被广泛应用,特别是在AOP、MVC、Security等模块中。

掌握装饰器模式不仅有助于理解框架的设计思想,还能在实际开发中提供更好的解决方案。通过理论学习、实践应用和源码分析,可以深入理解装饰器模式的精髓,并在面试和实际工作中灵活运用。

相关推荐
SamDeepThinking14 小时前
用设计模式重构核心业务代码的一次实战
java·后端·设计模式
青草地溪水旁15 小时前
设计模式(C++)详解——建造者模式(2)
c++·设计模式·建造者模式
九术沫17 小时前
装饰器模式在Spring中的案例
java·spring·装饰器模式
o0向阳而生0o17 小时前
102、23种设计模式之装饰器模式(11/23)
设计模式·装饰器模式
宁静致远202117 小时前
【C++设计模式】第五篇:装饰器模式
c++·设计模式·装饰器模式
IT灰猫20 小时前
C++轻量级配置管理器升级版
开发语言·c++·设计模式·配置管理·ini解析
大飞pkz20 小时前
【设计模式】题目小练2
开发语言·设计模式·c#·题目小练
不一样的少年_1 天前
Vue3 后台分页写腻了?我用 1 个 Hook 删掉 90% 重复代码(附源码)
前端·vue.js·设计模式
A阳俊yi1 天前
设计模式——七大常见设计原则
设计模式