装饰器模式

装饰器模式(Decorator )允许向一个现有的对象添加新的增强功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装

一般的,我们为了扩展一个类经常使用继承方式实现,但随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类。这个时候就可以通过装饰器模式动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。但缺点就是多层装饰比较复杂。

那它是怎么实现的呢?
通过先将具体功能职责划分好,对于每部分功能职责,都有一个实现了原始类接口的装饰器类,装饰器类可以有继承它的子类来添加额外的职责。装饰模式是直接继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

举例实现:

我们将创建一个 Shape 接口和实现了 Shape 接口的实体类。然后我们创建一个实现了 Shape 接口的抽象装饰类 ShapeDecorator,并把 Shape 对象作为它的实例变量。

RedShapeDecorator 是实现了 ShapeDecorator 的实体类。DecoratorPatternDemo 类使用 RedShapeDecorator 来装饰 Shape 对象。

具体代码实现步骤:菜鸟教程:装饰器模式

装饰器模式最经典的应用:Java IO 类

Java IO 类库非常庞大和复杂,负责 IO 数据的读取和写入。如果对 Java IO类做一下分类,我们可以从下面两个维度将它划分为四类。具体如下所示:

针对不同的读取和写入场景,Java IO 又在这四个父类基础之上,扩展出了很多子类。

由于IO库中需要很多性能的各种组合,如果用继承方法实现,那么每一种组合都需要一个类,这样会造成大量性能重复的类出现。如果使用装饰器模式,那么类的数目大大减少,性能的重复也减到最少。因此装饰器模式是IO中的基本模式。

适配器模式

适配器模式(Adapter)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

怎么实现的呢?
这是通过继承和依赖关系(这里具体指组合)实现的,适配器继承或依赖已有的对象,实现想要的目标接口。

举例实现:
有一个 MediaPlayer 接口和一个实现了 MediaPlayer 接口的实体类 AudioPlayer。默认情况下,AudioPlayer 可以播放 mp3 格式的音频文件。
我们还有另一个接口 AdvancedMediaPlayer 和实现了 AdvancedMediaPlayer 接口的实体类。该类可以播放 vlc 和 mp4 格式的文件。
我们想要让 AudioPlayer 播放其他格式的音频文件。为了实现这个功能,我们需要创建一个实现了 MediaPlayer 接口的适配器类 MediaAdapter,并使用 AdvancedMediaPlayer 对象来播放所需的格式。
AudioPlayer 使用适配器类 MediaAdapter 传递所需的音频类型,不需要知道能播放所需格式音频的实际类。AdapterPatternDemo 类使用 AudioPlayer 类来播放各种格式。


具体代码实现步骤:菜鸟教程:适配器模式

适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。上面案例中的适配器类就是个使用组合关系实现的对象适配器。MediaAdapter类和AdvancedMediaPlayer 类是组合关系,如果是继承关系,那就是类适配器了。

适配器模式应用场景有

  1. 封装有缺陷的接口设计;
  2. 统一多个类的接口设计;
    某个功能的实现依赖多个外部系统(或者说类)
  3. 替换依赖的外部系统;
    当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可以
    减少对代码的改动。
  4. 兼容老版本接口;
  5. 适配不同格式的数据;

适配器模式比较常见的应用: Java 日志

Java 中有很多日志框架,在项目开发中,我们常常用它们来打印日志信息。其中,比较常用的有 log4j、logback,以及 JDK 提供的 JUL(java.util.logging) 和 Apache 的JCL(Jakarta Commons Logging) 等。

大部分日志框架都提供了相似的功能,但它们却并没有实现统一的接口。
如果我们开发的是一个集成到其他系统的组件、框架、类库等,那日志框架的选择就没那么随意了。如果引入多个组件,每个组件使用的日志框架都不一样,那日志本身的管理工作就变得非常复杂。所以,为了解决这个问题,我们需要统一日志打印框架。

对于java开发者, Slf4j 这个日志框架你肯定不陌生,它相当于 JDBC 规范,提供了一套打印日志的统一接口规范。不过,它只定义了接口,并没有提供具体的实现,需要配合其他日志框架(log4j、logback……)来使用。而且它不仅仅提供了统一的接口定义,还提供了针对不同日志框架的适配器。对不同日志框架的接口进行二次封装,适配成统一的 Slf4j 接口定义。
并且Slf4j 不仅仅提供了从其他日志框架到 Slf4j 的适配器,还提供了反向适配器,也就是从 Slf4j 到其他日志框架的适配。

代理、装饰器、适配器 这3 种设计模式的特点和区别

代理模式:代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。

装饰器模式:装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。

适配器模式:适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。

装饰器模式和适配器模式相关推荐

  1. java-IO流(5)-IO流中的设计模式(装饰器模式和适配器模式)的介绍

    目录 1装饰器模式 1.1定义 1.2代码实现 1.3装饰器特点 1.4装饰器在IO流中的使用 2配适器模式 2.1Adapter适配器 2.2代码实例 2.3适配器特点 2.4适配器优缺点 2.5适 ...

  2. 【设计模式系列】5.装饰器模式和适配器模式

    目录 一.装饰器模式 二.适配器模式 1.类适配器 2.对象适配器 3.适配器模式的优缺点 一.装饰器模式 特点: 在不改变一个对象本身功能的基础上给对象增加新的功能,即功能增强: 如Java IO中 ...

  3. 装饰器模式与java.io包

    为什么80%的码农都做不了架构师?>>>    Decorator设计模式是典型的结构型模式(在GOF的那本模式的Bible中将模式分为:1.创建型模式:2.结构型模式:3.行为模式 ...

  4. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  5. java中装饰器_Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  6. 适配器模式、代理模式、装饰器模式使用场景区别

    适配器模式 适配器模式是提供和原先接口不一样的接口,做一个二次转换,原来的接口还是可以继续使用的. 代理模式 原先的接口是不能访问的(无权使用),只能通过代理来去访问原先接口.代理过程中可能会对原有接 ...

  7. 关于适配器模式、装饰器模式、桥接模式和代理模式的总结

    这4个设计模式有很多的相同点,比较容易混.在这里写一篇笔记总结下. 回顾下4个模式: 适配器模式:https://blog.csdn.net/qq_35976351/article/details/9 ...

  8. 适配器模式和装饰器模式区别

    适配器模式和装饰器模式都可以在原类文件方法的基础上修改.增强,但侧重点不一样, 适配器模式重在将一个接口转换为另一个接口 装饰器模式侧重对原类文件方法的增强,但接口还是同一个接口 适配器模式: 适配器 ...

  9. java设计模式----装饰器模式

    Decorator装饰器,顾名思义,就是动态地给一个对象添加一些额外的职责,就好比为房子进行装修一样.因此,装饰器模式具有如下的特征: 它必须具有一个装饰的对象. 它必须拥有与被装饰对象相同的接口. ...

最新文章

  1. JavaScript实现重置表单(reset)的方法
  2. 软件测试体系划分与职业素养
  3. 解决 Maven 报错 Non-resolvable parent POM ... was cached in the local repository, resolution will not be
  4. PhoneGap学习笔记(一) 框架搭建
  5. gdb 调试kvm虚拟机_GDB+QEMU调试内核模块(实践篇)
  6. 中国双鼓磁选机行业市场供需与战略研究报告
  7. 【求助】想知道Xcode怎么像devc一样调试程序
  8. java 开源 邮件系统_Java架构师方案—简单的邮件系统(附完整项目代码)
  9. 新建计算机管理员账户,Win10如何新建本地管理员账户
  10. C语言函数定义和函数调用
  11. mysql删除一行_MySql删除表中一行的实操方法
  12. 电驴服务器更新的作用,怎样更新eMule(电驴)服务器列表,有什么好处?
  13. Python量化交易平台:JQData | API使用文档(转)
  14. MySQL基础——DDL、DML、DQL、DCL语句
  15. linux服务器用lighttpd+mysql5+php5+SupeSite/X-Space+discuz构建社区门户
  16. App怎么推广最有效
  17. Plist Converter for mac(plist文件转换工具)
  18. U盘中的文件夹全变成应用程序格式如何解决?
  19. 刘强东继续动刀高管!多名VP被换,年底末位10%淘汰...
  20. HPUNIX环境常用查看硬件设备信息命令小结

热门文章

  1. vue结合websocket
  2. 21python_面向对象封装案例
  3. uni-app qiun-data-charts 2d模式 y轴消失报错
  4. php 把时间转为时间戳_php怎么把时间格式转换为时间戳?
  5. emqttd的启动脚本
  6. Mysql第三章:存储引擎(MyISAM和Innodb)
  7. WIN10 API打印CPU占用率
  8. Python机器学习16——相关向量机(RVM)
  9. 怎么办嘛,无法反驳!
  10. C语言简单程序:一个加法计算器