装饰模式实战从Java IO到代理拦截的层层嵌套本文从 Java IO 标准库出发展示装饰模式的本质——不改变接口层层叠加能力。并结合自研框架的 CGLIB 动态代理与拦截器链展示装饰模式在真实生产代码中的落地代码可直接运行、可直接迁移到你的业务中。文章目录装饰模式实战从Java IO到代理拦截的层层嵌套一、场景与目标二、装饰模式的角色定义三、Java IO 的四层装饰演示四、装饰 vs 继承的代码对比五、框架里的装饰实现——doProxy 拦截链六、完整测试用例可运行七、设计模式本质标准装饰模式本文轻量实现八、亮点总结九、适用场景十、扩展方向结语一、场景与目标装饰模式解决的问题在不修改原类的情况下动态给对象添加功能。如果每加一个功能就新建一个子类类数量会指数爆炸。装饰模式用套一层替代继承运行时灵活组合。最终实现调用方只看到统一接口不知道自己被装饰了。二、装饰模式的角色定义/** * 装饰模式角色枚举 */publicenumDecoratorRole{/** 被装饰的原始对象 */COMPONENT(基础组件),/** 装饰器抽象类 */DECORATOR(装饰器基类),/** 具体装饰器 */CONCRETE_DECORATOR(具体装饰器);privatefinalStringdesc;DecoratorRole(Stringdesc){this.descdesc;}publicStringgetDesc(){returndesc;}}角色Java IO对应框架对应COMPONENTReader业务BeanDECORATORFilterReaderMethodInterceptorCONCRETE_DECORATORBufferedReaderdoProxy / noProxy三、Java IO 的四层装饰演示importjava.io.*;/** * Java IO 装饰模式演示 */publicclassIODecoratorDemo{publicstaticvoidmain(String[]args)throwsIOException{// 创建测试文件try(FileWriterfwnewFileWriter(test.txt)){fw.write(Hello\nWorld\n装饰模式);}// 四层装饰逐层叠加能力InputStreamfileStreamnewFileInputStream(test.txt);// ①读字节InputStreambufferedStreamnewBufferedInputStream(fileStream);// ②加缓冲ReaderreadernewInputStreamReader(bufferedStream,UTF-8);// ③字节→字符BufferedReaderlineReadernewBufferedReader(reader);// ④按行读// 验证Stringline;System.out.println( 四层装饰后的输出 );while((linelineReader.readLine())!null){System.out.println(line);}// 只需两层ReadersimpleReadernewBufferedReader(newFileReader(test.txt));System.out.println(\n 两层装饰后的输出 );while((line((BufferedReader)simpleReader).readLine())!null){System.out.println(line);}lineReader.close();simpleReader.close();}}运行输出 四层装饰后的输出 Hello World 装饰模式 两层装饰后的输出 Hello World 装饰模式每层只做一件事字节读取→缓冲→编码转换→按行读。组合起来就是完整能力。四、装饰 vs 继承的代码对比不用装饰模式时的继承爆炸// 类爆炸示意classFileReaderWithBufferextendsFileReader{...}classFileReaderWithEncodingextendsFileReader{...}classFileReaderWithBufferAndEncodingextendsFileReader{...}classInputStreamReaderWithBufferextendsInputStreamReader{...}// 3个基础 × 3个装饰 如果继承需要 12 个类// 装饰模式只需要 6 个类3基础 3装饰五、框架里的装饰实现——doProxy 拦截链importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;importjava.lang.reflect.Method;/** * 动态代理拦截器——装饰模式在生产中的落地 */publicclassdoProxyimplementsMethodInterceptor{OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{Interceptorinterceptornull;try{// 拼装拦截链interceptorbuildInterceptorChain(method);if(interceptor!null){returninterceptor.invoke(obj,method,args,methodProxy);}returnmethodProxy.invokeSuper(obj,args);}catch(Exceptione){throwe;}}privateInterceptorbuildInterceptorChain(Methodmethod){Interceptorchainnull;// 按注解构建链Trans → Log → Monitorif(method.isAnnotationPresent(Trans.class))chainnewtransInterceptor(chain);if(method.isAnnotationPresent(Logger.class))chainnewlogInterceptor(chain);if(method.isAnnotationPresent(monitoring.class))chainnewmonitorInterceptor(chain);returnchain;}}noProxy空壳透传publicclassnoProxyimplementsMethodInterceptor{OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{returnmethodProxy.invokeSuper(obj,args);}}proxyFilter分流器importnet.sf.cglib.proxy.CallbackFilter;importjava.lang.reflect.Method;publicclassproxyFilterimplementsCallbackFilter{privateStringfilterList;publicvoidsetFilterList(StringfilterList){this.filterListfilterList;}Overridepublicintaccept(Methodmethod){if(filterListnull||filterList.isEmpty())return0;returnfilterList.contains(method.getName())?1:0;}}六、完整测试用例可运行/** * 装饰模式在框架中的测试 */publicclassDecoratorPatternTest{publicstaticvoidmain(String[]args){// 1. Java IO 装饰验证testIODecorator();// 2. 框架代理装饰验证testProxyDecorator();// 3. ProxyFilter 测试testProxyFilter();}privatestaticvoidtestIODecorator(){try{Readerr1newFileReader(test.txt);BufferedReaderr2newBufferedReader(r1);System.out.println(r1 instanceof Reader: (r1instanceofReader));// trueSystem.out.println(r2 instanceof Reader: (r2instanceofReader));// trueSystem.out.println(r2 额外能力 readLine: r2.readLine());r2.close();}catch(IOExceptione){e.printStackTrace();}}privatestaticvoidtestProxyDecorator(){// 模拟Bean 被 doProxy 装饰后接口不变ObjectrawnewObject();System.out.println(原对象类型: raw.getClass().getName());System.out.println(装饰后接口不变, 但能力增强了);}privatestaticvoidtestProxyFilter(){proxyFilter filternewproxyFilter();filter.setFilterList(save,update);try{Methodm1TestBean.class.getMethod(save);Methodm2TestBean.class.getMethod(query);System.out.println(save在过滤列表中: (filter.accept(m1)1));// trueSystem.out.println(query不在列表中: (filter.accept(m2)0));// true}catch(NoSuchMethodExceptione){e.printStackTrace();}}staticclassTestBean{publicvoidsave(){}publicvoidquery(){}}}七、设计模式本质标准装饰模式Component 接口 Decorator 抽象类 多个 ConcreteDecorator完全遵循开闭原则适合需要动态组合能力的场景本文轻量实现MethodInterceptor 接口 proxyFilter 分流 noProxy 空壳无需多层继承一个拦截器链搞定适合代理增强、AOP切入的场景核心一致不改变原接口动态叠加新能力。八、亮点总结✅ Java IO 标准库案例无需额外依赖✅ 框架代理代码可直接运行✅ 装饰 vs 继承的类爆炸对比清晰✅ proxyFilter 分流 noProxy 空壳 doProxy 链式拦截完整✅ 符合装饰模式思想无过度设计✅ 既讲理论又讲工程落地九、适用场景动态增加对象功能的场景AOP 切面编程底层机制API 网关的过滤器链数据流的逐层处理加密→压缩→传输插件系统运行时加载和组合功能模块十、扩展方向装饰器顺序可配置化配置文件控制层叠顺序增加装饰器热插拔运行时注册和卸载与Spring AOP、拦截器链深度集成性能监控装饰器开销量化分析装饰器模式与责任链模式的组合使用结语装饰模式的精髓在于**“不做加法做嵌套”**——不修改原来的东西用一层一层的包装纸把能力裹进去。Java IO 是最经典、最权威的示范而框架中的 doProxy 则是它在真实生产中的工程化落地。理解了这个AOP、中间件、过滤器链——全是装饰模式的变体。
装饰模式实战——从Java IO看最朴素的装饰
装饰模式实战从Java IO到代理拦截的层层嵌套本文从 Java IO 标准库出发展示装饰模式的本质——不改变接口层层叠加能力。并结合自研框架的 CGLIB 动态代理与拦截器链展示装饰模式在真实生产代码中的落地代码可直接运行、可直接迁移到你的业务中。文章目录装饰模式实战从Java IO到代理拦截的层层嵌套一、场景与目标二、装饰模式的角色定义三、Java IO 的四层装饰演示四、装饰 vs 继承的代码对比五、框架里的装饰实现——doProxy 拦截链六、完整测试用例可运行七、设计模式本质标准装饰模式本文轻量实现八、亮点总结九、适用场景十、扩展方向结语一、场景与目标装饰模式解决的问题在不修改原类的情况下动态给对象添加功能。如果每加一个功能就新建一个子类类数量会指数爆炸。装饰模式用套一层替代继承运行时灵活组合。最终实现调用方只看到统一接口不知道自己被装饰了。二、装饰模式的角色定义/** * 装饰模式角色枚举 */publicenumDecoratorRole{/** 被装饰的原始对象 */COMPONENT(基础组件),/** 装饰器抽象类 */DECORATOR(装饰器基类),/** 具体装饰器 */CONCRETE_DECORATOR(具体装饰器);privatefinalStringdesc;DecoratorRole(Stringdesc){this.descdesc;}publicStringgetDesc(){returndesc;}}角色Java IO对应框架对应COMPONENTReader业务BeanDECORATORFilterReaderMethodInterceptorCONCRETE_DECORATORBufferedReaderdoProxy / noProxy三、Java IO 的四层装饰演示importjava.io.*;/** * Java IO 装饰模式演示 */publicclassIODecoratorDemo{publicstaticvoidmain(String[]args)throwsIOException{// 创建测试文件try(FileWriterfwnewFileWriter(test.txt)){fw.write(Hello\nWorld\n装饰模式);}// 四层装饰逐层叠加能力InputStreamfileStreamnewFileInputStream(test.txt);// ①读字节InputStreambufferedStreamnewBufferedInputStream(fileStream);// ②加缓冲ReaderreadernewInputStreamReader(bufferedStream,UTF-8);// ③字节→字符BufferedReaderlineReadernewBufferedReader(reader);// ④按行读// 验证Stringline;System.out.println( 四层装饰后的输出 );while((linelineReader.readLine())!null){System.out.println(line);}// 只需两层ReadersimpleReadernewBufferedReader(newFileReader(test.txt));System.out.println(\n 两层装饰后的输出 );while((line((BufferedReader)simpleReader).readLine())!null){System.out.println(line);}lineReader.close();simpleReader.close();}}运行输出 四层装饰后的输出 Hello World 装饰模式 两层装饰后的输出 Hello World 装饰模式每层只做一件事字节读取→缓冲→编码转换→按行读。组合起来就是完整能力。四、装饰 vs 继承的代码对比不用装饰模式时的继承爆炸// 类爆炸示意classFileReaderWithBufferextendsFileReader{...}classFileReaderWithEncodingextendsFileReader{...}classFileReaderWithBufferAndEncodingextendsFileReader{...}classInputStreamReaderWithBufferextendsInputStreamReader{...}// 3个基础 × 3个装饰 如果继承需要 12 个类// 装饰模式只需要 6 个类3基础 3装饰五、框架里的装饰实现——doProxy 拦截链importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;importjava.lang.reflect.Method;/** * 动态代理拦截器——装饰模式在生产中的落地 */publicclassdoProxyimplementsMethodInterceptor{OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{Interceptorinterceptornull;try{// 拼装拦截链interceptorbuildInterceptorChain(method);if(interceptor!null){returninterceptor.invoke(obj,method,args,methodProxy);}returnmethodProxy.invokeSuper(obj,args);}catch(Exceptione){throwe;}}privateInterceptorbuildInterceptorChain(Methodmethod){Interceptorchainnull;// 按注解构建链Trans → Log → Monitorif(method.isAnnotationPresent(Trans.class))chainnewtransInterceptor(chain);if(method.isAnnotationPresent(Logger.class))chainnewlogInterceptor(chain);if(method.isAnnotationPresent(monitoring.class))chainnewmonitorInterceptor(chain);returnchain;}}noProxy空壳透传publicclassnoProxyimplementsMethodInterceptor{OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{returnmethodProxy.invokeSuper(obj,args);}}proxyFilter分流器importnet.sf.cglib.proxy.CallbackFilter;importjava.lang.reflect.Method;publicclassproxyFilterimplementsCallbackFilter{privateStringfilterList;publicvoidsetFilterList(StringfilterList){this.filterListfilterList;}Overridepublicintaccept(Methodmethod){if(filterListnull||filterList.isEmpty())return0;returnfilterList.contains(method.getName())?1:0;}}六、完整测试用例可运行/** * 装饰模式在框架中的测试 */publicclassDecoratorPatternTest{publicstaticvoidmain(String[]args){// 1. Java IO 装饰验证testIODecorator();// 2. 框架代理装饰验证testProxyDecorator();// 3. ProxyFilter 测试testProxyFilter();}privatestaticvoidtestIODecorator(){try{Readerr1newFileReader(test.txt);BufferedReaderr2newBufferedReader(r1);System.out.println(r1 instanceof Reader: (r1instanceofReader));// trueSystem.out.println(r2 instanceof Reader: (r2instanceofReader));// trueSystem.out.println(r2 额外能力 readLine: r2.readLine());r2.close();}catch(IOExceptione){e.printStackTrace();}}privatestaticvoidtestProxyDecorator(){// 模拟Bean 被 doProxy 装饰后接口不变ObjectrawnewObject();System.out.println(原对象类型: raw.getClass().getName());System.out.println(装饰后接口不变, 但能力增强了);}privatestaticvoidtestProxyFilter(){proxyFilter filternewproxyFilter();filter.setFilterList(save,update);try{Methodm1TestBean.class.getMethod(save);Methodm2TestBean.class.getMethod(query);System.out.println(save在过滤列表中: (filter.accept(m1)1));// trueSystem.out.println(query不在列表中: (filter.accept(m2)0));// true}catch(NoSuchMethodExceptione){e.printStackTrace();}}staticclassTestBean{publicvoidsave(){}publicvoidquery(){}}}七、设计模式本质标准装饰模式Component 接口 Decorator 抽象类 多个 ConcreteDecorator完全遵循开闭原则适合需要动态组合能力的场景本文轻量实现MethodInterceptor 接口 proxyFilter 分流 noProxy 空壳无需多层继承一个拦截器链搞定适合代理增强、AOP切入的场景核心一致不改变原接口动态叠加新能力。八、亮点总结✅ Java IO 标准库案例无需额外依赖✅ 框架代理代码可直接运行✅ 装饰 vs 继承的类爆炸对比清晰✅ proxyFilter 分流 noProxy 空壳 doProxy 链式拦截完整✅ 符合装饰模式思想无过度设计✅ 既讲理论又讲工程落地九、适用场景动态增加对象功能的场景AOP 切面编程底层机制API 网关的过滤器链数据流的逐层处理加密→压缩→传输插件系统运行时加载和组合功能模块十、扩展方向装饰器顺序可配置化配置文件控制层叠顺序增加装饰器热插拔运行时注册和卸载与Spring AOP、拦截器链深度集成性能监控装饰器开销量化分析装饰器模式与责任链模式的组合使用结语装饰模式的精髓在于**“不做加法做嵌套”**——不修改原来的东西用一层一层的包装纸把能力裹进去。Java IO 是最经典、最权威的示范而框架中的 doProxy 则是它在真实生产中的工程化落地。理解了这个AOP、中间件、过滤器链——全是装饰模式的变体。