设计模式——装饰者模式

更多内容,前往 IT-BLOG

现实生活中常常需要给某类产品动态增加新的功能,如:给面条各种调味品。在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成一些核心功能。但在不改变其架构的情况下,可以动态地扩展其功能。所以这些都可以采用装饰模式来实现。

一、装饰者定义

【1】装饰者模式: 动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则。
【2】设计模式属于结构型模式。
【3】这种模式创建一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
【4】优点: 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
【5】缺点: 多层装饰比较复杂。

二、装饰者类图

在这里插入图片描述

三、案例代码分析

【1】定义一个装饰者和被装饰者都需要集成的抽象类(Food 食物)

public abstract class Food {
    private String des;
    private Double price;
 
    //其他类需要实现的抽象方法
    public abstract double cost();
        //get/set方法省略
}

【2】被装饰者需要继承的类(Noodles 面条)

public class Noodles extends Food{
    //这里获取到的价格是子类实现时设置的价格
    @Override
    public double cost() {
        return super.getPrice();
    }
}

【3】被装饰者具体的实现类之一(ChineseNoodles 中式面条)

public class ChineseNoodles extends Noodles{
    //构造器中只需要定义该产品的价格和描述,因为它是被装饰者,与平常类一样
    public ChineseNoodles() {
        setDes("中式面条");
        setPrice(25.00);
    }
}

【4】装饰者类都需要集成的公共类

public class Decorator extends Food{
    //将被装饰者组合进来
    private Food desFood;
    //构造器将其引入
    public Decorator(Food desFood) {
        this.desFood = desFood;
    }
    //将自己的价格与被装饰者价格进行成绩
    @Override
    public double cost() {
        System.out.println(desFood.getDes() +"价格:"+desFood.getPrice()+ "配料如下:"
                +super.getDes()+"价格:"+this.getPrice()+"总价"+(super.getPrice()+desFood.cost()) );
        //价格总计
        return super.getPrice()+desFood.cost();
    }
}

【5】装饰者实现类之一

//孜然类
public class Cumin extends Decorator{
    //构造器
    public Cumin(Food desFood) {
        super(desFood);
        setDes("孜然");
        setPrice(2.00);
    }
}

【6】客户端调用: 优点,一个产品可以被多个装饰者装饰,同时装饰者和被装饰者扩展时都非常灵活,只需要扩展自己的类即可,无需修改其他类。

public class Client {
    public static void main(String[] args) {
        //先定义一个被装饰者,返回对象要为最顶层的对象,这样被装饰者才能接受
        Food noodles = new ChineseNoodles();
        //定义一个装饰者对象
        Food cumin = new Cumin(noodles);
        //输出为:中式面条价格:25.0配料如下:孜然价格:2.0
        cumin.cost();
 
        //再定义一个装饰者 Pepper辣椒类
        Food pepper = new Pepper(cumin);
        //输出为:中式面条价格:25.0配料如下:孜然价格:2.0配料如下:辣椒价格:1.0总价28.0
        pepper.cost();
    }
}

四、装饰者模式在JDK应用的源码分析

【1】JDK 中流的使用用到了装饰者模式。从下面的客户端使用能够得出 FileInputStream 是被装饰者,DataInputStream 是装饰者类的一个实现类,下面就进入 FileInputStream 中查看源代码:

public class Decorator {
    public static void main(String[] args) throws Exception{
        DataInputStream dis = new DataInputStream(new FileInputStream("d:\\a.txt"));
    }
}

【2】FileInputStream 继承了 InputStream ,也就是上面提到的 Food 类及 ChineseNoodles 之间的关系。

public class FileInputStream extends InputStream{  
    ......  
}

【3】进入 DataInputStream 装饰者类的实现类

public class DataInputStream extends FilterInputStream implements DataInput {
 
    /**
     * 构造器,将顶层接口 进行组合,父类装饰类的重写
     */
    public DataInputStream(InputStream in) {
        super(in);
    }
}

【4】最重要的部分:装饰者类 FilterInputStream 继承和组合了 InputStream 接口,被装饰者也实现了此接口。

//集成最顶层 InputStream 接口,被装饰者也集成的接口,因为此类的返回值要与被装饰类类型相同
public class FilterInputStream extends InputStream {
    /**
     * 组合 被装饰者类
     */
    protected volatile InputStream in;
 
    /**
     * 构造器
     */
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
}

【5】源码类图如下:与装饰者类的类图一致,易理解。

在这里插入图片描述

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

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

相关文章

Java毕业设计-基于jsp+servlet的大学生学业规划咨询服务平台管理系统-第84期

获取源码资料,请移步从戎源码网:从戎源码网_专业的计算机毕业设计网站 项目介绍 基于jspservlet的大学生学业规划咨询服务平台管理系统:前端 jsp、jquery、ajax,后端 servlet、jdbc,角色分为管理员、学生&#xff1b…

C++ :命名空间域

目录 冲突与命名: 举个例子: 全局与局部: 域作用限定符: 命名空间域: 冲突与命名: 在C语言中,我们通常会使用stdlib.h 而stdlib.h 本质上是一个函数的库,在程序中使用的大多数…

C++(14)——string的模拟实现

前几篇文章中介绍了关于以及其相关函数的使用,为了更清楚的了解这些函数的作用,本篇文章通过模拟实现的方式来加深对于函数作用原理的理解。 目录 1. String的整体框架: 1.1 成员变量: 1.2 构造函数: 1.3 析构函数…

第十一站:多态练习ODU

实现动态切换 ODU.h #pragma once #include <iostream> using namespace std; #define ODU_TYPE_311_FLAG "311" #define ODU_TYPE_335_FLAG "335" enum class ODU_TYPE {ODU_TYPE_311,ODU_TYPE_335,ODU_TYPE_UNKNOW };class ODU{ public:ODU();//发…

Elasticsearch的映射操作

本文来记录下Elasticsearch的映射操作 文章目录 映射的概述 映射的概述 Elasticsearch与mysql数据库对比 映射的概述 有了索引库&#xff0c;等于有了数据库中的 database。索引库(index)中的映射&#xff0c;类似于数据库(database)中的表结构(table)。创建数据库表需要设置字…

SpringBoot实现文件上传和下载实现全过程(值得珍藏)

1. 引言 在Web应用中&#xff0c;文件上传和下载是常见的需求。Spring Boot框架提供了强大的支持和便利的API&#xff0c;使得开发者可以轻松地实现文件上传和下载功能。本文将详细介绍如何在Spring Boot应用中实现文件上传和下载&#xff0c;包括实现原理和完整的代码示例。 …

【js】js 异步机制详解 Generator / Async / Promise

三种语法功能放在一起&#xff0c;是因为他们都有相似特点&#xff1a; 维护某种状态在未来恢复状态并执行 本文重点回答以下几个问题&#xff1a; 为什么 Generator 和 Async 函数的 代码执行流 都可以简化成树形结构&#xff1f;async 函数为什么返回一个 promise&#xf…

list下

文章目录 注意&#xff1a;const迭代器怎么写&#xff1f;运用场合&#xff1f; inserterase析构函数赋值和拷贝构造区别&#xff1f;拷贝构造不能写那个swap,为什么&#xff1f;拷贝构造代码 面试问题什么是迭代器失效&#xff1f;vector、list的区别&#xff1f; 完整代码 注…

3、非数值型的分类变量

非数值型的分类变量 有很多非数字的数据,这里介绍如何使用它来进行机器学习。 在本教程中,您将了解什么是分类变量,以及处理此类数据的三种方法。 本课程所需数据集夸克网盘下载链接:https://pan.quark.cn/s/9b4e9a1246b2 提取码:uDzP 文章目录 1、简介2、三种方法的使用1…

idea运行卡顿优化方案

文章目录 前言一、调整配置1. idea.properties2. idea.vmoptions3.heap size4.Plugins5.Inspections 总结 前言 本人电脑16G内存&#xff0c;处理器i7 10代&#xff0c;磁盘空间也够用&#xff0c;整体配置够用&#xff0c;但运行idea会很卡&#xff0c;记录优化过程&#xff…

Linux中关于head命令详解

head的作用 head用于查看文件的开头部分的内容。 head的参数 -q隐藏文件名-v 显示文件名-c<数目>显示的字节数-n<数目>显示的行数 head的案例 # 查看yum.log前五行内容 head -5 yum.log

文件操作和IO(1)

认识文件 先来认识狭义上的文件(存储在硬盘(磁盘)上).针对硬盘这种持久化的I/O设备,当我们想要进行数据保存时,往往不是保存成一个整体,而是独立成一个个的单位进行保存,这个独立的单位就被抽象成文件的概念,就类似办公桌上的一份份真实的文件一般. 注意:硬盘 ! 磁盘 磁盘属于…

1885_Arduino 1306 OLED屏幕的使用

全部学习汇总&#xff1a; g_arduino: Arduino hack笔记 (gitee.com) 以前我基于Arduino做过一个环境信息采集的小工具&#xff0c;采集到的信息存储到SD卡中。当时的笔记&#xff1a; 341_Arduinopython分析天气变化导致颈椎病发的原因_颈椎病相关数据分析python-CSDN博客 以前…

Jan AI本地运行揭秘:首次体验,尝鲜科技前沿

&#x1f31f;&#x1f30c; 欢迎来到知识与创意的殿堂 — 远见阁小民的世界&#xff01;&#x1f680; &#x1f31f;&#x1f9ed; 在这里&#xff0c;我们一起探索技术的奥秘&#xff0c;一起在知识的海洋中遨游。 &#x1f31f;&#x1f9ed; 在这里&#xff0c;每个错误都…

关于Hive架构原理,尚硅谷

最近学习hive 时候&#xff0c;在做一个实操案例&#xff0c;具体大概是这样子的&#xff1a; 我在dataGip里建了一个表&#xff0c;然后在hadoop集群创建一个文本文件里面存储了数据库表的数据信息&#xff0c;然后把他上传到hdfs后&#xff0c;dataGrip那个表也同步了我上传到…

gin渲染篇

1. 各种数据格式的响应 json、结构体、XML、YAML类似于java的properties、ProtoBuf package mainimport ("github.com/gin-gonic/gin""github.com/gin-gonic/gin/testdata/protoexample" )// 多种响应方式 func main() {// 1.创建路由// 默认使用了2个中…

java idea 中的 Scratches and Consoles

IDEA 中&#xff0c;"Scratches and Consoles" 是一个用于临时代码编辑和交互式开发的工具窗口&#xff0c;作用如下&#xff1a;Scratches&#xff08;草稿&#xff09;&#xff1a;Scratches 是一个用于临时编写和运行代码片段的工具&#xff0c;你可以在其中创建临…

四.Winform使用Webview2加载本地HTML页面并互相通信

Winform使用Webview2加载本地HTML页面并互相通信 往期目录本节目标核心代码实现HTML代码实现的窗体Demo2代码效果图 往期目录 往期相关文章目录 专栏目录 本节目标 实现刷新按钮点击 C# winform按钮可以调用C# winform代码显示到html上点击HTML按钮可以调用C# winform代码更…

2024首更---Web Service 教程

Web Services 简介 Web Services 可使您的应用程序成为 Web 应用程序。 Web Services 通过 Web 进行发布、查找和使用。 您应当具备的基础知识 在继续学习之前&#xff0c;您需要对下面的知识有基本的了解&#xff1a; HTMLXML 如果您希望首先学习这些项目&#xff0c;请在…

万户 ezOFFICE wf_process_attrelate_aiframe.jsp SQL注入漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…