【设计模式】结构型设计模式之 从IO流设计思想来看装饰器模式

介绍

装饰器模式也称为包装模式(Wrapper Pattern) 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。
装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。

装饰器模式代码举例

实现逻辑

  1. 装饰器类和原始类实现共同的父类,下方案例中的 Coffe
  2. 装饰器类,组合原始类的对象作为目标对象
  3. 装饰器类重写需要装饰的方法,并且重写的内容中可以调用原始类的对象方法。
  4. 通过中间层的装饰器基类,避免实现每个共同父类的方法

代码

//装饰器和目标类基础接口
public interface Coffee {
    String getDescription();
    double getCost();
}

//具体的咖啡,什么都不加
public class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "Simple Coffee";
    }

    @Override
    public double getCost() {
        return 1.0;
    }
}

//装饰器基类,为了避免每个装饰器都要手动重新实现共同父类的接口,即使该装饰器不需要装饰对应方法
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    @Override
    public abstract String getDescription();

    @Override
    public double getCost() {
        return decoratedCoffee.getCost();
    }
}

//摩卡咖啡装饰器,增加风味描述、增加价格
public class MochaDecorator extends CoffeeDecorator {
    public MochaDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription() + ", Mocha";
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.5;
    }
}

//奶油装饰器,增加奶油、增加价格
public class WhipDecorator extends CoffeeDecorator {
    public WhipDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription() + ", Whip";
    }

    @Override
    public double getCost() {
        return super.getCost() + 0.3;
    }
}


//测试类
public class Main {
    public static void main(String[] args) {
        // 创建一杯简单的咖啡
        Coffee simpleCoffee = new SimpleCoffee();
        
        // 添加摩卡装饰
        Coffee mochaCoffee = new MochaDecorator(simpleCoffee);
        
        // 再添加奶泡装饰
        Coffee finalCoffee = new WhipDecorator(mochaCoffee);
        
        System.out.println(finalCoffee.getDescription() + " costs $" + finalCoffee.getCost());
    }
}


Simple Coffee, Mocha, Whip costs $1.8

IO 类库的装饰器模式

为什么没有 BufferdFileInputStream

在 JAVA 的 IO 类库中,例如如果让 FileInputStream 支持 BufferdInputStream,需要让 需要间接的将 FileInputStream 传递给 BufferdInputStream。为什么 Java 不直接支持BufferdFileInputStream 呢。

InputStream in = new FileInputStream("");
InputStream bin = new BufferedInputStream(in);

为什么不基于继承实现 BufferedFileInputStream

  1. 如果 InputStream 类只有一个子类 FileInputStream 那么再在 FileInputStream 下面实现一个BufferedInputStream 也没有什么问题
  2. 问题在于 InputStream 的子类太多了,如果每个子类都单独实现 Buffered 功能和 DataInputStream 的功能那么类的数量将会爆炸性增多。

IO 类库使用装饰模式实现

  1. 在设计原则中,组合优于继承,针对继承结构过于复杂的问题可以将继承关系转换为组合关系来解决。
  2. 所以 IO 类库中,对于 BufferedInputStream 没有选择对所有的 InputStream 实现一遍,而是只实现一遍通过组合目标 InputStream 来实现增强功能
  3. 对于需要实现 Buffered 的功能的 inputStream,只需使用BufferedInputStream 对其进行一次包装即可实现。
  4. 并且如果想要实现 DataInputStream 的按照数据类型读取,只需要再次添加一层包装即可。

总结&思考

总结

  1. 装饰器模式可以解决继承关系过于复杂的问题,通过组合关系替代继承关系。
  2. 装饰器模式主要的作用是给原始类添加增强功能,除此之外装饰器模式还支持嵌套使用,为了满足这个功能装饰器类和原始类都继承自相同的父类或者接口。
  3. 装饰器模式和静态代理模很相似,都是通过组合来对原始类进行增强,主要区别是代理模式主要对原始类不相关的功能进行增强,但是装饰器模式是对原始类相关功能的增强。

IO 类库的 FilterInputStream 的作用是什么

  1. 和案例中的装饰类基类作用一样,提供 InputStream 需要实现的方法的实现。方法的具体执行通过委托给组合的 InputStream 对象实现。
  2. 如果没有 FilterInputStream,那么每个装饰器类,都需要对 InputStream 的方法提供实现,即使是委托给组合的 InputStream 成员对象执行也会很麻烦。

装饰器类和原始类有相同的父类的作用

装饰器类和原始类有相同的父类,例如 InputStream 和 Coffee 可以实现对原始类进行“嵌套”多个装饰器类来进行增强。例如对 FileInputStream 包装 BufferedInputStream 后再包装一层 DataInputStream,这样既实现了缓存读取又实现类按照基本数据类型来读取。

和其他组合代替继承的设计模式(例如代理模式)的区别

代理模式中,代理类附加的是原始类不相关的功能,但是装饰器模式中附加的是与原始类相关的增强功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/710049.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

内网不能访问网站怎么办?

内网不能访问网站是在网络使用过程中常见的问题之一。当我们使用局域网连接时,有时候会遇到无法访问特定网站的情况。这可能是因为网络环境复杂,或者受到了某些限制。本篇文章将介绍一种解决内网不能访问网站问题的产品——天联组网。 天联组网是一款由…

C#开发-集合使用和技巧(二)Lambda 表达式介绍和应用

C#开发-集合使用和技巧 Lambda 表达式介绍和应用 C#开发-集合使用和技巧介绍简单的示例:集合查询示例: 1. 基本语法从主体语句上区分:1. 主体为单一表达式2. 主体是代码块(多个表达式语句) 从参数上区分1. 带输入参数的…

【odoo | XML-RPC】odoo外部API解读,实现跨系统间的通讯!

概要 文章注意对官方的XML-RPC进行解读实操,以python为例,给大家介绍其使用方式和调用方法。 内容 什么是odoo的外部API? Odoo 的外部 API 是一种允许外部应用程序与 Odoo 实例进行交互的接口。通过 API,可以执行各种操作,例如…

移动端超超超详细知识点总结(Part3)

flex布局体验 1. 传统布局与flex布局 传统布局: 兼容性好布局繁琐局限性,不能再移动端很好的布局flex 弹性布局: 操作方便,布局极为简单,移动端应用很广泛PC 端浏览器支持情况较差IE 11或更低版本,不支持…

宝藏速成秘籍(7)堆排序法

一、前言 1.1、概念 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法 。堆是一个近似 完全二叉树 的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。 1.2、排…

Uni-App中的u-datetime-picker时间选择器Demo

目录 前言Demo 前言 对于网页端的推荐阅读:【ElementUI】详细分析DatePicker 日期选择器 事情起因是两个时间选择器同步了,本身是从后端慢慢步入全栈,对此将这个知识点从实战进行提炼 通过Demo进行总结 Demo 用于选择日期和时间的组件&a…

zookeeper介绍 和 编译踩坑

zookeeper 分布式协调服务 ZooKeeper原理及介绍 - 鹿泉 - 博客园 Zookeeper是在分布式环境中应用非常广泛,它的优秀功能很多,比如分布式环境中全局命名服务,服务注册中心,全局分布式锁等等。 本项目使用其分布式服务配置中心&am…

Java--数组的使用

1.普通For循环(用的最多,需从中取出数据以及下标) eg:图中三类问题都可 2.For-each循环(一般用来打印一些结果) eg:打印数组的具体元素 3.数组作方法入参(对数组进行一些操作&#x…

【实例分享】银河麒麟高级服务器操作系统环境资源占用异常-情况分析及处理方法

1.情况描述 使用vsftp进行文件传输,发现sshd进程cpu占用异常,并且su和ssh登录相比正常机器会慢2秒左右。 图1 2.问题分析 通过strace跟踪su和sshd进程,有大量ssh:notty信息。 图2 配置ssh绕过pam模块认证后,ssh连接速…

外观模式(大话设计模式)C/C++版本

外观模式 C #include <iostream> using namespace std;class stock1 { public:void Sell(){cout << "股票1卖出" << endl;}void Buy(){cout << "股票1买入" << endl;} };class stock2 { public:void Sell(){cout <<…

C++设计模式——Decorator装饰器模式

一&#xff0c;装饰器模式简介 装饰器模式是一种结构型设计模式&#xff0c; 它允许在不改变现有对象的情况下&#xff0c;动态地将功能添加到对象中。 装饰器模式是通过创建具有新行为的对象来实现的&#xff0c;这些对象将原始对象进行了包装。 装饰器模式遵循开放/关闭原…

AI办公自动化:批量在多个Word文档中插入对应图片

工作任务&#xff1a;文件夹中有多个word文档和word文档名称一致的图片&#xff0c;要把这些图片都插入到word文档中 在chatpgt中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;写一个Python脚本&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;F:…

c++/c输出double问题

这个我大抵能理解&#xff0c;%d是int嘛。 这是为啥&#xff1f; 这样又好了&#xff1f; 这我也能理解 这也可以 这也对&#xff1f; &#xff08;我知道我呢个函数为什么不对了&#xff0c;我的函数写的是int(&#xff09;) 附&#xff1a;保留几位小数&#xff1a; %.2f

手把手教你入门vue+springboot开发(三)--登录功能后端

文章目录 前言一、redis安装二、后端代码1.修改application.yml文件2.增加utils文件3.增加Result类4.修改UserController类5.修改UserMapper类6.修改UserService和UserServiceImpl类7.增加LoginInterceptor类8.增加WebConfig类9.修改pom.xml文件 前言 前两篇我们用vuespringbo…

基于负相关误差函数的4集成BP神经网络matlab建模与仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ...............................................................…

XILINX 7系列XDMA使用_IP核介绍以及工程搭建

文章目录 一、XDMA IP核1.1、接口说明1.2、配置页说明 二、XDMA工程搭建2.1、BD搭建2.2 Linux下XDMA驱动安装2.3 Linux下使用XDMA进行数据传输 一、XDMA IP核 1.1、接口说明 sys_clk&#xff1a;主机给PCIE提供的时钟信号&#xff0c;通过原理图查看 sys_rst_n&#xff1a;主机…

宠物健康顾问系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;顾问管理&#xff0c;用户管理&#xff0c;健康知识管理&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;公告管理 顾问账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;顾…

宝藏速成秘籍(3)选择排序法

一、前言 1.1、概念 选择排序法&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。它的基本思想是&#xff1a;每次从待排序的数组中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放在已排序部分的末尾&#xff0c;直到所有元素都排序完毕。…

资源分享—2021版乡级制图规范符号库

汇总整理超图平台软件相关的各类资源&#xff08;包括但不限于符号库、地图模板、地理处理模型等&#xff09;&#xff0c;助力项目的高效制图、提高数据生产效率等业务。 本次分享新版国土空间规划【2021版乡级制图规范符号库】&#xff0c;提供SuperMap格式符号库下载。 符…

简单了解CPU的工作原理

目录 一、基本结构以及对应功能 &#xff08;1&#xff09;基本结构 &#xff08;2&#xff09;几个重要寄存器的详细介绍 操作码 (Opcode) 操作数 (Operands) 指令表 (Instruction Table) 第一个&#xff1a;程序计数器 (PC) 第二个&#xff1a;指令寄存器 (IR&#x…