包装模式就是这么简单啦

论文分享 - OctoMap八叉树建图原理 论文:OctoMap:An Efficient Probabilistic 3D Mapping Framework Based on Octrees。 阅读详情

前言

只有光头才能变强

回顾前面:

前一篇已经讲解了代理模式了,今天要讲解的就是装饰模式啦~

在看到FilterInputStream和FilterOutputStream时看到了之前常听见的装饰模式(对IO一定了解的同学可能都会知道那么一句话:在IO用得最多的就是装饰模式了)!

其实无论是代理模式还是装饰模式。本质上我认为就是对原有对象增强的方式~

那么接下来就开始吧,如果文章有错误的地方请大家多多包涵,不吝在评论区指正哦~

声明:本文使用JDK1.8

一、对象增强的常用方式

很多时候我们可能对Java提供给我们的对象不满意,不能满足我们的功能。此时我们就想对Java原对象进行增强,能够实现我们想要的功能就好~

一般来说,实现对象增强有三种方式:

1.1继承

最简单的方式就是继承父类,子类扩展来达到目的。虽然简单,但是这种方式的缺陷非常大:

  • 一、如果父类是带有数据、信息、属性的话,那么子类无法增强。
  • 二、子类实现了之后需求无法变更,增强的内容是固定的。

1.1.1第一点

第一点就拿以前在学JDBC的时候来说:

  • 当时想要自己写一个简易的JDBC连接池,连接池由List<Connection>来管理。显然我们的对象是Connection,当写到close()方法的时候卡住了。
  • 因为我们想要的功能是:调用close()是让我们的Connection返回到“连接池”(集合)中,而不是关闭掉。
  • 此时我们不能使用继承父类的方式来实现增强。因为Connection对象是由数据库厂商来实现的,在得到Connection对象的时候绑定了各种信息(数据库的username、password、具体的数据库是啥等等)。我们子类继承Connection是无法得到对应的数据的!就更别说调用close()方法了。

1.1.2第二点

第二点我也举个例子:

现在我设计一个电话类:


public class Phone {
    // 可以打电话
    public void call() {
        System.out.println("打电话给周围的人关注公众号Java3y");
    }
}

此时,我想打电话之前能听彩铃,于是我继承Phone类,实现我想要的功能。


public class MusicPhone extends Phone {

    // 听彩铃
    public void listenMusic() {
        System.out.println("我怀念的是无话不说,我怀念的是一起做梦~~~~~~");
    }

    @Override
    public void call() {

        // 在打电话之前听彩铃
        listenMusic();

        super.call();
    }
}

我们的功能就做好了:

  • 此时,我又突然想实现多一个需求了,我想要听完电话之后告诉我一下当前的时间是多少。没事,我们又继承来增强一下:

// 这里继承的是MusicPhone类
public class GiveCurrentTimePhone extends MusicPhone {

    // 给出当前的时间
    public void currentTime() {
        System.out.println("当前的时间是:" + System.currentTimeMillis());
    }

    @Override
    public void call() {
        super.call();

        // 打完电话提示现在的时间是多少啦
        currentTime();
    }
}

所以我们还是可以完成任务滴:

可是我需求现在又想变了:

  • 我不想听彩铃了,只想听完电话通知一下时间就好了……..(可是我们的通知时间电话类是继承在听彩铃的电话类基础之上的),,,
  • 我又有可能:我想在听电话之前报告一下时间,听完电话听音乐!…
  • 如果需求变动很大的情况下,而我们又用继承的方式来实现这样会导致一种现象:类爆炸(类数量激增)!并且继承的层次可能会比较多~

所以,我们可以看到子类继承父类这种方式来扩展是十分局限的,不灵活的~

因此我们就有了装饰模式!

1.2装饰模式

首先我们来看看装饰模式是怎么用的吧。

1.2.1前提代码

电话接口:


// 一个良好的设计是抽取成接口或者抽象类的
public interface Phone {

    // 可以打电话
    void call();
}

具体的实现:


public class IphoneX implements Phone {


    @Override
    public void call() {
        System.out.println("打电话给周围的人关注公众号Java3y");
    }
}

1.2.2包装模式实现

上面我们已经拥有了一个接口还有一个默认实现。包装模式是这样干的:

首先我们弄一个装饰器,它实现了接口,以组合的方式接收我们的默认实现类。


// 装饰器,实现接口
public abstract class PhoneDecorate implements Phone {

    // 以组合的方式来获取默认实现类
    private Phone phone;
    public PhoneDecorate(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void call() {
        phone.call();
    }
}

有了装饰器以后,我们的扩展都可以以装饰器为基础进行扩展,继承装饰器来扩展就好了!

我们想要在打电话之前听音乐:


// 继承着装饰器来扩展
public class MusicPhone extends PhoneDecorate {

    public MusicPhone(Phone phone) {
        super(phone);
    }

    // 定义想要扩展的功能
    public void listenMusic() {

        System.out.println("继续跑 带着赤子的骄傲,生命的闪耀不坚持到底怎能看到,与其苟延残喘不如纵情燃烧");

    }

    // 重写打电话的方法
    @Override
    public void call() {

        // 在打电话之前听音乐
        listenMusic();
        super.call();
    }
}

现在我也想在打完电话后通知当前的时间,于是我们也继承装饰类来扩展:


// 这里继承的是MusicPhone装饰器类
public class GiveCurrentTimePhone extends PhoneDecorate  {


    public GiveCurrentTimePhone(Phone phone) {
        super(phone);
    }

    // 自定义想要实现的功能:给出当前的时间
    public void currentTime() {
        System.out.println("当前的时间是:" + System.currentTimeMillis());
    }

    // 重写要增强的方法
    @Override
    public void call() {
        super.call();
        // 打完电话后通知一下当前时间
        currentTime();
    }
}

可以完成任务:

就目前这样看起来,比我直接继承父类要麻烦,而功能效果是一样的….我们继续往下看~~

此时,我不想在打电话之前听到彩铃了,很简单:我们不装饰它就好了!

此时,我想在打电话前报告一下时间,在打完电话之后听彩铃。

  • 注意:虽然说要改动类中的代码,但是这种改动是合理的。因为我定义出的GiveCurrentTimePhone类和MusicPhone类本身从语义上就没有规定扩展功能的执行顺序
  • 而继承不一样:先继承Phone->实现MusicPhone->再继承MusicPhone实现GiveCurrentTimePhone。这是固定的,从继承的逻辑上已经写死了具体的代码,是难以改变的。

所以我们还是可以很简单地完成功能:

二、装饰模式讲解

可能有的同学在看完上面的代码之后,还是迷迷糊糊地不知道装饰模式是怎么实现“装饰”的。下面我就再来解析一下:

  • 第一步:我们有一个Phone接口,该接口定义了Phone的功能
  • 第二步:我们有一个最简单的实现类iPhoneX
  • 第三步:写一个装饰器抽象类PhoneDecorate,以组合(构造函数传递)的方式接收我们最简单的实现类iPhoneX。其实装饰器抽象类的作用就是代理(核心的功能还是由最简单的实现类iPhoneX来做,只不过在扩展的时候可以添加一些没有的功能而已)。
  • 第四步:想要扩展什么功能,就继承PhoneDecorate装饰器抽象类,将想要增强的对象(最简单的实现类iPhoneX或者已经被增强过的对象)传进去,完成我们的扩展!

再来看看下面的图,就懂了!

往往我们的代码可以省略起来,成了这个样子(是不是和IO的非常像!)


    // 先增强听音乐的功能,再增强通知时间的功能
    Phone phone = new GiveCurrentTimePhone(new MusicPhone(new IphoneX()));

结果是一样的:

2.1装饰模式的优缺点

优点:

  • 装饰类和被装饰类是可以独立的,低耦合的。互相都不用知道对方的存在
  • 装饰模式是继承的一种替代方案,无论包装多少层,返回的对象都是is-a的关系(上面的例子:包装完还是Phone类型)。
  • 实现动态扩展,只要继承了装饰器就可以动态扩展想要的功能了。

缺点:

  • 多层装饰是比较复杂的,提高了系统的复杂度。不利于我们调试~

三、总结

最后来补充一下包装模式和代理模式的类图:

对象增强的三种方式:

  • 继承
  • 包装模式
  • 代理模式

那么只要遇到Java提供给我们的API不够用,我们增强一下就行了。在写代码时,某个类被写死了,功能不够用,增强一下就可以了!

理解包装模式,接下来就开始IO之旅咯~~~

参考资料:

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y。为了大家方便,刚新建了一下qq群:742919422,大家也可以去交流交流。谢谢支持了!希望能多介绍给其他有需要的朋友

文章的目录导航:

手把手教你完成YOLOv11分类识别界面搭建,使用Qt6设计YOLOv11分类识别系统,前台系统+后台管理系统开发实战,全网最详细教程 本项目结合YOLOv11分类识别算法和PySide6框架,开发了一套图形化分类识别系统。系统支持图片、视频和摄像头实时分类检测,并具备完善的用户管理功能,包括登录验证、个人信息修改等模块。最新版本新增了管理员后台管理系统,包含用户管理、权限控制等功能。系统采用MySQL数据库存储用户数据,界面设计采用QtDesigner完成,实现了高效的目标分类与友好的交互体验。 阅读详情

相关推荐

SAP BASIS运维之三方SSL证书导入

事情的起因是我司SAP使用的SSL证书即将要到期了(上一个的SAP BASIS也辞职了),需要进行证书的更换。如上图所示,我司的证书有效期到2024年4月30日到期,需要提前预防并更换,防止过期后导致接口和访问出现问题。9.在弹出的框中,选择我们在第5个步骤中导出的转换结果存储地址,并选择导出的转换文件,点打开。12.最后一步也是关键的一步,不然就会无法更新证书,再点击左上角的个人安全环境,点另存为。10.在打开后的弹窗中,输入我们在第4个步骤中设置的密码。6.经过以上步骤后,我们获得了最终的证书文件。

fegda的专栏 1885

装饰器模式(Decorator Pattern)

装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

FH的博客 1001

oracle两节点RAC,由于gipc导致某节点crs无法启动问题分析

两节点RAC,其中1 节点集群CRS无法启动。经过分析原因为2节点gipcd进程异常,导致节点之间无法正常通信,重启2节点gipcd.bin后问题得以恢复。 从现象来看,是 ora.crsd...

cuibaye0692的博客 4535

设计模式第7讲——装饰者模式(Decorator)

装饰者模式是一种结构型设计模式。一、什么是装饰者模式 二、角色组成 三、优缺点 四、应用场景 4.1 应用实例 4.2 java实例 五、代码实现5.0 UML类图5.1 Hero(英雄-抽象组件)5.2 BlindMonk(盲僧-具体构件)5.3 SkillDecorator(技能装饰-抽象装饰器)5.4 QDecorator(Q技能-具体装饰器)5.5 WDecorator(W技能-具体装饰器)5.6 EDecorator(E技能-具体装饰器)5.7

让~学习~成为一种习惯(橡 皮 人の技术博客) 6798

Halcon实战:5分钟搞定灰度图转热力图(附完整代码)

本文提供了一份Halcon实战指南,详细讲解如何在5分钟内将灰度图转换为直观的热力图。通过核心代码演示了利用HSV颜色模型进行色彩映射的原理与步骤,包括图像归一化、通道构建与空间转换,并附赠了深度图可视化等进阶应用技巧,帮助工程师快速提升图像分析效果。

weixin_29240343的博客 282

FPGA开发者必看:如何用SATA3.0主机控制器IP实现高速存储扩展(附Xilinx实测数据)

本文为FPGA开发者提供了基于SATA3.0主机控制器IP核的高速存储方案设计与优化指南。通过详细解析IP核架构、Xilinx FPGA平台集成实战及性能优化技巧,帮助开发者实现接近理论极限的540MB/s数据传输速度。文章还包含常见问题解决方案和高级应用场景拓展,是硬件工程师提升存储性能的必备参考。

weixin_30632089的博客 114

23种设计模式——装饰者模式

文章目录23种设计模式——装饰者模式1、装饰者模式概述2、装饰者模式的结构3、装饰者模式的实现4、装饰者模式的应用场景 23种设计模式——装饰者模式 1、装饰者模式概述 背景 有些人为了早上多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框、咖啡加调料等,都是装饰器模式。 装饰者模式的定义 装饰者(Decorator)模式的定义:指在不改

万里顾一程的博客 5291

STM32 HAL库ADC+DMA配置详解:从CubeMX到实战调试

在嵌入式系统开发中,模数转换器(ADC)是实现传感器数据采集、信号处理等功能的基石。其工作原理是将连续的模拟信号转换为离散的数字量,为微控制器(MCU)提供可处理的数字信息。为了提升系统效率,直接存储器访问(DMA)技术被引入,它作为独立于CPU的数据搬运工,能在不占用CPU资源的情况下,自动完成外设与内存间的数据传输,从而解放CPU以执行更复杂的控制算法或通信任务。这种ADC与DMA的协同工作模式,对于实现高效、实时的数据流处理具有重要价值,广泛应用于电机控制、环境监测、音频处理等场景。本文聚焦于STM3

weixin_30698297的博客 408

设计模式之【装饰者模式】,实现“穿衣打扮”自由原来这么简单

装饰者模式(Decorator Pattern),也称为包装模式(Wrapper Pattern)、装饰器模式,是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。在 GoF 的《设计模式》一书中,对装饰者模式是这样理解的:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式相比生成子类更灵活。装饰者模式的核心是扩展功能。使用装饰者模式可以透明且动态地扩展类的功能。装饰器模式主要解决。

秃了也弱了 2331

SAP LSMW数据批导操作手册及跨客户端传输方法(涉及默认值配置,及多余字段如何删除)

SAP LSMW数据批导操作手册及跨客户端传输方法

我好像病了的博客 6087

DISK配置服务器软RAID工作任务(RAID1+BITLOCKER)-winserver4

DISK配置服务器软RAID工作任务(RAID1+BITLOCKER)-winserver4

新时代先锋的博客 7299

设计模式-装饰者模式(Decorator)

装饰者模式(Decorator Pattern)是一种结构型设计模式,它的定义是在不改变原有对象结构的基础上,动态地给该对象增加一些职责(即增加其额外功能)。这种模式允许向一个现有的对象添加新的功能,同时又不改变其结构。它是继承的一种替代方案,可以实现在运行时动态地扩展对象的行为,而无需修改原有代码。

m0_51176516的博客 2109

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

JAVA学习笔记----简单工厂模式,模板模式,包装类

简单工厂模式:采用工厂的思维,其实就是利用工厂对象来创建需要的对象,首先,工厂对象要采用单例模式,即私有化其构造方法,在工厂内部创建工厂对象并将其私有,再在工厂类里编写获得工厂对象的静态方法(一般命名为getInstance),当外部程序需要获得工厂对象时,直接用工厂类名.getInstance()即可获得工厂对象为什么要建立工厂:为了方便创建对象,即一个工厂可以创建多个同一类型的对象。要实现此种...

jiangzihao110120的博客 518

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Day11:内部类、内存分析、单例设计模式、简单工厂设计模式、基本数据类型包装类

一、内部类 内部类:一个类里声明另外一个类,内部类可声明成public或private 变量:成员变量、静态变量、局部变量 内部类: 成员内部类、静态内部类、接口内部类、局部内部类、匿名内部类 1、成员内部类 public class Outter { String str1="字符串1"; //成员内部类 public class Inner{ ...

亲爱的瑶的博客 236

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

spring包装hibernate_不懂Spring的9种设计模式,面试会吃亏的

导读:设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆。Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行内典范。好了,话不多说,开始今天的内容。spring中常用的设计模式达到九种,我们举例说明。一、简单工厂模式又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。简...

weixin_39713538的博客 86

spring包装hibernate_面试官:Spring中用了哪些设计模式?

前言设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆。Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行内典范。好了,话不多说,开始今天的内容。spring中常用的设计模式达到九种,我们举例说明。以后再也不怕面试官问我:Spring中用了哪些设计模式了。1简单工厂模式又叫做静态工厂方法(StaticFactory M...

weixin_39855796的博客 95

javaIO流06:节点流和处理流(包装流)(以代码的方式简单理解处理流的装饰者模式)

VV

m0_52051155的博客 348

Spring中用了哪些设计模式

设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆。 Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行内典范。好了,话不多说,开始今天的内容。 spring中常用的设计模式达到九种,我们一一举例: 第一种:简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种...

琦彦 5849

java中关于设计模式的总结

java中关于设计模式的总结 1.单例模式: 单列模式就是调用该单例类的方法所获得的对象始终是唯一的。 eg: public class Foo { private static Foo instance = new Foo(); private Foo() {} public static Foo getInstance() { return instance; } }

Jack Zhu 2905

Spring中用到的设计模式

Spring中用到的设计模式Spring常用的设计模式有九种简单工厂工厂方法(Factory Method)单例模式(Singleton) Spring常用的设计模式有九种 简单工厂 又叫做静态工厂方法(staticFactory Method)模式,但不属于23种GOF设计模式之一。 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。 spring种的Bean Fac...

mc_csdn的博客 734

Spring中用到的九种设计模式

spring中常用的设计模式达到九种,我们举例说明:第一种:简单工厂又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。 spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得bean对象,但是否是在传入参数后创建还是传入参数前创建这...

大道至简 3万+

初探设计模式5:Spring涉及到的9种设计模式

设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记忆。今天,螃蟹在IT学习者网站就设计模式的内在价值做一番探讨,并以spring为例进行讲解,只有领略了其设计的思想理念,才能在工作学习中运用到“无形”。Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行内典范。好了,话不多说,开始今天的内容。spring中常用的设计模式达...

weixin_34414650的博客 148
上一篇: 给女朋友讲解什么是代理模式
下一篇: 看完这篇Linux基本的操作就会了
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值