Spring + 设计模式 (七) 结构型 - 装饰器模式

装饰器模式

引言

装饰器模式(Decorator Pattern)是一种结构型设计模式,核心在于动态地为对象添加新功能,而无需修改其原有代码。它通过包装现有对象,层层扩展行为,保持接口一致性,仿佛为对象披上"功能外衣"。装饰器模式强调灵活性和可扩展性,特别适合需要动态组合功能的场景,如日志记录、权限控制或数据过滤,优雅实现"开闭原则"。

实际开发中的用途

在实际开发中,装饰器模式广泛用于需要动态增强对象行为的场景,如Web应用的请求过滤、数据流的加密压缩或日志追踪。它解决了硬编码功能的紧耦合问题,允许运行时自由组合功能,提升代码复用性和可维护性。例如,在REST API中,装饰器可为响应添加认证、日志或格式化功能,无需更改核心业务逻辑,特别适合模块化、高扩展性的企业级系统。

开发中的示例

设想一个订单处理系统,核心功能是计算订单总价。现需动态添加折扣、税费或赠品逻辑。若直接修改订单类,代码将变得臃肿且难以维护。通过装饰器模式,可定义一个订单接口,核心订单类实现基本计算逻辑,再通过装饰器类动态添加折扣或税费功能。客户端只需组合所需装饰器,即可灵活生成不同功能的订单对象,保持代码清晰且易于扩展。

Spring 源码中的应用

CachingClientHttpRequestFactory 是Spring Web模块中用于增强ClientHttpRequestFactory的一个装饰器实现(Spring 5.x及以上版本)。它通过包装底层的ClientHttpRequestFactory(如SimpleClientHttpRequestFactory或HttpComponentsClientHttpRequestFactory),为HTTP请求添加缓存功能,从而减少重复请求,提高性能。

下面是个详细的例子

java 复制代码
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        // 创建底层的ClientHttpRequestFactory
        ClientHttpRequestFactory simpleFactory = new SimpleClientHttpRequestFactory();

        // 使用CachingClientHttpRequestFactory装饰
        CachingClientHttpRequestFactory cachingFactory = 
            new CachingClientHttpRequestFactory(simpleFactory);

        // 创建RestTemplate并注入装饰后的工厂
        return new RestTemplate(cachingFactory);
    }
}
@Service
public class ApiService {

    @Autowired
    private RestTemplate restTemplate;

    public String fetchPost(int postId) {
        String url = "https://api.disjfhjxkb.com:8080?postId=" + postId;
        return restTemplate.getForObject(url, String.class);
    }
}

@RestController
public class ApiController {

    @Autowired
    private ApiService apiService;

    @GetMapping("/post/{id}")
    public String getPost(@PathVariable int id) {
        return apiService.fetchPost(id);
    }
}

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

这段代码体现了装饰器模式的核心价值:透明增强职责分离。在实际开发中,这种模式广泛用于性能优化、日志记录等场景

优点

  • 透明性:客户端使用装饰后的对象时,接口保持一致,无需修改调用代码。
  • 灵活性:可以动态添加或移除缓存功能。
  • 复用性:缓存逻辑与HTTP请求逻辑解耦,可应用于不同的请求工厂。

Java I/O系统的装饰器模式详解

装饰器模式(Decorator Pattern)是Java I/O系统中最重要的设计模式之一,它允许在不修改原有对象结构的情况下动态地扩展功能。

1. 装饰器模式在Java I/O中的实现原理

1. 基本结构

Java I/O中的装饰器模式遵循以下结构:

  • 抽象组件(Component) : InputStream/OutputStream(字节流) 或 Reader/Writer(字符流)
  • 具体组件(ConcreteComponent) : FileInputStream, FileOutputStream
  • 装饰器(Decorator) : FilterInputStream, FilterOutputStream
  • 具体装饰器(ConcreteDecorator) : BufferedInputStream, DataInputStream
2. 核心特点
  • 装饰器和被装饰对象实现相同的接口
  • 装饰器内部持有被装饰对象的引用
  • 可以在运行时动态添加功能

2. 具体代码演示

示例1:基本的装饰器使用
java 复制代码
import java.io.*;

public class DecoratorDemo {
    public static void main(String[] args) {
        try {
            // 1. 创建基础文件输入流(具体组件)
            InputStream fileStream = new FileInputStream("test.txt");
            
            // 2. 添加缓冲功能(第一次装饰)
            InputStream bufferedStream = new BufferedInputStream(fileStream);
            
            // 3. 添加数据读取功能(第二次装饰)
            DataInputStream dataStream = new DataInputStream(bufferedStream);
            
            // 使用装饰后的流读取数据
            int data = dataStream.readInt();
            System.out.println("读取的数据: " + data);
            
            // 关闭流(只需要关闭最外层的装饰器)
            dataStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
示例2:自定义装饰器实现
java 复制代码
import java.io.*;

// 自定义装饰器 - 将输入流转换为大写
class UpperCaseInputStream extends FilterInputStream {
    public UpperCaseInputStream(InputStream in) {
        super(in);
    }
    
    @Override
    public int read() throws IOException {
        int c = super.read();
        return (c == -1) ? c : Character.toUpperCase((char)c);
    }
    
    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int result = super.read(b, off, len);
        for (int i = off; i < off + result; i++) {
            b[i] = (byte)Character.toUpperCase((char)b[i]);
        }
        return result;
    }
}

public class CustomDecoratorDemo {
    public static void main(String[] args) {
        try {
            String text = "hello, decorator pattern!";
            
            // 创建字节数组输入流
            InputStream in = new ByteArrayInputStream(text.getBytes());
            
            // 使用自定义装饰器
            InputStream upperIn = new UpperCaseInputStream(in);
            
            // 读取并打印装饰后的数据
            int c;
            while ((c = upperIn.read()) != -1) {
                System.out.print((char)c);
            }
            
            upperIn.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

装饰器模式的详细说明

1. Java I/O中装饰器类的关系

scss 复制代码
InputStream (抽象组件)
├── FileInputStream (具体组件)
├── FilterInputStream (抽象装饰器)
│   ├── BufferedInputStream (具体装饰器)
│   ├── DataInputStream (具体装饰器)
│   ├── PushbackInputStream (具体装饰器)
│   └── ...其他装饰器
└── ...其他具体组件

2. 装饰器模式的优势

  1. 灵活性:可以动态组合功能,如缓冲+数据读取+行号跟踪
  2. 避免类爆炸:不需要为每种功能组合创建子类
  3. 开闭原则:不修改原有代码即可扩展功能
  4. 运行时配置:可以在运行时决定如何装饰对象

3. 装饰器模式的典型应用场景

  1. 添加缓冲功能BufferedInputStream/BufferedOutputStream
  2. 添加基本数据类型读写DataInputStream/DataOutputStream
  3. 添加行号跟踪LineNumberReader
  4. 添加推回功能PushbackInputStream
  5. 添加字符编码转换InputStreamReader/OutputStreamWriter

4. 使用注意事项

  1. 关闭流:只需要关闭最外层的装饰器,内层流会自动关闭
  2. 装饰顺序:装饰顺序有时会影响性能,如缓冲流应该尽可能靠近原始流
  3. 性能考虑:过多的装饰层会增加方法调用开销

与继承方式的对比

假设不使用装饰器模式,要为文件流添加缓冲和数据读取功能,可能需要:

java 复制代码
class BufferedFileInputStream extends FileInputStream {...}
class DataBufferedFileInputStream extends BufferedFileInputStream {...}
class BufferedDataFileInputStream extends DataFileInputStream {...}
// 组合爆炸...

而使用装饰器模式,只需要:

java 复制代码
InputStream in = new DataInputStream(
                 new BufferedInputStream(
                 new FileInputStream("file.txt")));

这种组合方式明显更加灵活和可维护。

Java I/O系统中的装饰器模式通过灵活的包装机制,使得各种流处理功能可以像"俄罗斯套娃"一样层层叠加,既保持了类的单一职责原则,又提供了无限的功能组合可能性。理解这一模式对于高效使用Java I/O系统至关重要。

总结

装饰器模式如同一件裁剪精良的"功能外套",动态为对象披上新能力,既优雅又灵活。在 Spring 中,HandlerExecutionChain 通过装饰器模式实现请求的动态增强,赋予框架强大的扩展性。结合 Spring Boot,开发者可轻松构建高内聚、低耦合的系统,应对复杂需求。掌握装饰器模式,不仅能写出模块化的代码,更能设计出如 Spring 般动态可扩展的架构,让功能组合如艺术般流畅。

(对您有帮助 && 觉得我总结的还行) -> 受累点个免费的赞👍,谢谢

相关推荐
晨米酱10 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机15 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
金銀銅鐵15 小时前
Spring 中的 initializeBean 方法的内部逻辑小总结
spring
数据智能老司机16 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机16 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机16 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤16 小时前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机1 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript