码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 设计模式——装饰器模式(Decorator Pattern)+ Spring相关源码


    文章目录

    • 一、装饰器模式的定义
    • 二、个人理解
      • 举个抽象的例(可能并不是很贴切)
    • 三、例子
      • 1、菜鸟教程例子
        • 1.1、定义对象
        • 1.2、定义装饰器
      • 3、JDK源码 ——包装类
      • 4、JDK源码 —— IO、OutputStreamWriter
      • 5、Spring源码 —— BeanWrapperImpl
      • 5、SpringMVC源码 —— HttpHeadResponseDecorator
    • 四、其他设计模式

    一、装饰器模式的定义

    • 别名:包装模式(Wrapper Pattern)
    • 类型:结构型模式。
    • 目的:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责额外功能。

    二、个人理解

    给对象添加新功能时,并不是在对象类中直接添加,而是在装饰器类中添加。
    在装饰类中添加新功能,你可以增强原先对象的方法,也可以给对象新增一个方法。

    举个抽象的例(可能并不是很贴切)

    假设要给人类添加开炮功能。
    但由于这是人类,咱们不能通过继承直接给人类添加开炮功能;
    所以我们就得通过组合,将机器和人类组合起来、通过变相实现人类可以开炮。
    这个机器就是装饰器。

    • 坦克 + 人类 ,实现开炮功能
    • 高达 + 人类 ,实现开炮功能

    三、例子

    1、菜鸟教程例子

    菜鸟教程的例子都将对象和装饰器进行了抽象处理,实现了可替换对象和装饰器的实现类。
    菜鸟教程原例子
    个人觉得这样理解装饰器太绕了,下面的例子就只保留了对象和装饰器。

    1.1、定义对象

    定义一个圆的对象

    public class Circle{
       @Override
       public void draw() {
          System.out.println("Shape: Circle");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.2、定义装饰器

    新增setRedBorder方法去设置红色边框。

    public class RedCircleDecorator{
       private Circle c;
       public RedCircleDecorator(Circle c) {
          this.c = c;
       }
     
       @Override
       public void draw() {
          decoratedShape.draw();         
          setRedBorder(decoratedShape);
       }
     
       private void setRedBorder(Circle decoratedShape){
          System.out.println("Border Color: Red");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    但我觉这个菜鸟这个例子并不能把装饰器模式特点表现出来。
    因setRedBorder是私有,并且只是把原先draw方法进行了增强。
    这样的话,代理模式也能实现,代理模式也能增强原有的方法,所以这里并不能把装饰器模式特点表现出来。
    所以我改了一下。

    public class ColorCircleDecorator{
       private Circle c;
       public RedCircleDecorator(Circle c) {
          this.c = c;
       }
     
       @Override
       public void draw() {
          decoratedShape.draw();
          System.out.println("画了个普通的圆");         
       }
     
       public void drawRedCircle(Circle decoratedShape){
       	  decoratedShape.draw();
          System.out.println("画了个红色的圆");
       }
       public void drawBlueCircle(Circle decoratedShape){
          decoratedShape.draw();
          System.out.println("画了个蓝色的圆");
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这个例子保留了原先的draw功能,又新增了drawRedCircle和drawBlueCircle功能。

    3、JDK源码 ——包装类

    包装类也运用了装饰器模式。
    将基本类型 转 包装类 的同时,还提供各种转换类型的功能。

    4、JDK源码 —— IO、OutputStreamWriter

    OutputStreamWriter同时运用了装饰器模式+适配器模式。
    这里我们拿装饰器部分来讲。

    FileOutputStream fos = new FileOutputStream(new File("Y:/学习资料.md"));
    OutputStreamWriter osw = new OutputStreamWriter(fos);
    osw.append("新资料xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    
    • 1
    • 2
    • 3

    原本FileOutputStream 是原本没有append功能的,
    而在中OutputStreamWriter 添加append功能。
    源码:

    public class OutputStreamWriter extends Writer {
    	private final StreamEncoder se;
    	
    	public OutputStreamWriter(OutputStream out) {
            super(out);
            se = StreamEncoder.forOutputStreamWriter(out, lockFor(this),
                    out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());
        }
        @Override
        public Writer append(CharSequence csq) throws IOException {
            if (csq instanceof CharBuffer) {
                se.write((CharBuffer) csq);
            } else {
                se.write(String.valueOf(csq));
            }
            return this;
        }
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    可以看到虽然OutputStreamWriter 重写了append方法。
    但构造器里OutputStream又被新的装饰器StreamEncoder接收。
    而StreamEncoder类就已经通过继承Writer 增加了append方法。

    public final class StreamEncoder extends Writer {
    	private final OutputStream out;
        private StreamEncoder(OutputStream out, Object lock, CharsetEncoder enc) {
            super(lock);
            this.out = out;
            this.ch = null;
            this.cs = enc.charset();
            this.encoder = enc;
    
            this.bb = ByteBuffer.allocate(INITIAL_BYTE_BUFFER_CAPACITY);
            this.maxBufferCapacity = MAX_BYTE_BUFFER_CAPACITY;
        }
    	public static StreamEncoder forOutputStreamWriter(OutputStream out, Object lock, Charset cs) {
            return new StreamEncoder(out, lock, cs);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    5、Spring源码 —— BeanWrapperImpl

    BeanWrapperImpl类是对BeanWrapper接口的默认实现,它包装了一个bean对象,缓存了bean的内省结果,并可以访问bean的属性、设置bean的属性值。

    BeanWrapperImpl功能还挺复杂的,大家可以自行去看源码,我就不贴出来了。

    5、SpringMVC源码 —— HttpHeadResponseDecorator

    HttpHeadResponseDecorator 给ServerHttpResponse 添加了writeWith、writeAndFlushWith的功能。

    public class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {
        public HttpHeadResponseDecorator(ServerHttpResponse delegate) {
            super(delegate);
        }
    
        public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
            return this.shouldSetContentLength() && body instanceof Mono ? ((Mono)body).doOnSuccess((buffer) -> {
                if (buffer != null) {
                    this.getHeaders().setContentLength((long)buffer.readableByteCount());
                    DataBufferUtils.release(buffer);
                } else {
                    this.getHeaders().setContentLength(0L);
                }
    
            }).then() : Flux.from(body).doOnNext(DataBufferUtils::release).then();
        }
    
        private boolean shouldSetContentLength() {
            return this.getHeaders().getFirst("Content-Length") == null && this.getHeaders().getFirst("Transfer-Encoding") == null;
        }
    
        public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
            return this.setComplete();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    四、其他设计模式

    创建型模式
    结构型模式

    • 1、设计模式——装饰器模式(Decorator Pattern)+ Spring相关源码

    行为型模式

    • 1、设计模式——访问者模式(Visitor Pattern)+ Spring相关源码
    • 2、设计模式——中介者模式(Mediator Pattern)+ JDK相关源码
    • 3、设计模式——策略模式(Strategy Pattern)+ Spring相关源码
    • 4、设计模式——状态模式(State Pattern)
    • 5、设计模式——命令模式(Command Pattern)+ Spring相关源码
    • 6、设计模式——观察者模式(Observer Pattern)+ Spring相关源码
    • 7、设计模式——备忘录模式(Memento Pattern)
    • 8、设计模式——模板方法模式(Template Pattern)+ Spring相关源码
    • 9、设计模式——迭代器模式(Iterator Pattern)+ Spring相关源码
    • 10、设计模式——责任链模式(Chain of Responsibility Pattern)+ Spring相关源码
    • 11、设计模式——解释器模式(Interpreter Pattern)+ Spring相关源码
  • 相关阅读:
    全局后置路由守卫(afterEach)
    【C#】使用Windows窗体实现链接跳转功能
    React——简便获取经纬度信息
    力扣刷题学习SQL篇——1-3 选择(从不订购的客户——使用not in)
    双目视觉实战--单视图测量方法
    JDBC-环境搭建及简单介绍和使用
    40.组合总和 II
    MCSM面板搭建教程和我的世界Paper服务器开服教程
    【知识图谱】概述
    如何一键转发朋友圈,快速跟圈?
  • 原文地址:https://blog.csdn.net/malu_record/article/details/134063321
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号