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

news2024/12/23 9:29:01

深入理解装饰者模式

  • 一、装饰者模式简介
    • 1.1 定义
    • 1.2 模式类型
    • 1.3 主要作用
    • 1.4 优点
    • 1.5 缺点
  • 二、模式动机
  • 三、模式结构
  • 四、 装饰者模式的实现
    • 4.1 组件接口
    • 4.2 具体组件
    • 4.3 装饰者抽象类
    • 4.4 具体装饰者
    • 4.5 使用装饰者模式
    • 4.6 输出结果:
  • 五、 应用场景
    • 5.1 图形用户界面
    • 5.2 数据流处理
    • 5.3 日志功能
    • 5.4 监控和计数
  • 六、总结

在这里插入图片描述

一、装饰者模式简介

1.1 定义


  装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地向对象添加新的功能,而不改变其结构和实现。装饰者模式通过组合来实现功能的扩展,它将功能划分成单一职责的类,并在需要时动态地组合这些功能实例化对象。

  根据《设计模式:可复用面向对象软件的基础》一书的定义,装饰者模式是:

动态地给对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活。

1.2 模式类型


  结构型

1.3 主要作用


  1. 扩展功能:允许在运行时动态地给对象添加新的功能,而不需要修改对象的结构。这有助于遵循 OCP 原则。
  2. 灵活性和可重用性:装饰者模式通过创建装饰类来包裹原始对象,并在装饰类中添加功能,这样可以灵活组合不同的装饰器以达到不同的功能组合,同时原始类和装饰类都可以独立复用。
  3. 简化复杂度:对于有大量可选功能的对象,如果使用继承来实现每种可能的功能组合,会导致类的数量爆炸式增长。装饰者模式通过组合而非继承的方式来添加功能,大大减少了类的数量,简化了系统的复杂度。
  4. 保持接口一致性:装饰者模式保持了被装饰对象的接口一致,客户端代码可以透明地使用装饰后的对象,无需关心是否以及如何被装饰,这有利于代码的维护和扩展。
  5. 易于管理对象的责任:每个装饰者都负责单一职责,即添加特定的功能,这使得对象的责任更加清晰,便于管理和调试。

1.4 优点


  1. 灵活性高:可以在运行时任意组合装饰者,动态地扩展对象功能。
  2. 符合单一职责原则:每个装饰者类只负责增加一种功能,类的职责更加单一。
  3. 降低类复杂度:相比通过继承扩展功能,装饰者模式避免了大量的子类生成,从而减少类的复杂度。

1.5 缺点


  1. 对象数量增多:由于装饰者和被装饰者都是对象,这会增加系统中对象的数量,增加管理成本。
  2. 依赖过多:容易产生过多的小型对象,增加系统复杂性,理解和维护变得更加困难。

二、模式动机


装饰者模式的主要动机是应对以下几个问题:

  • 避免类爆炸:通过继承添加新功能会导致子类数量激增,维护起来十分困难。
  • 灵活组合功能:继承的组合方式是静态的,不够灵活。装饰者模式允许动态地组合功能。
  • 单一职责原则:通过将功能分解到不同的装饰类中,装饰者模式使每个类的职责更加单一,代码更易读易维护。

三、模式结构

在这里插入图片描述

装饰者模式通常涉及以下几个角色:

  • Component(抽象组件):定义一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent(具体组件):实现 Component 接口的具体对象,可以给这些对象添加一些职责。
  • Decorator(装饰者抽象类):继承 Component 接口,通常持有一个 Component 对象的引用,并定义一个与 Component 接口一致的接口。
  • ConcreteDecorator(具体装饰者):扩展 Decorator 类的具体装饰者,负责向组件添加新的职责。

四、 装饰者模式的实现


  我们将以一个具体的咖啡示例来介绍装饰者模式的实现。在这个例子中,我们有一个基本的咖啡对象,可以动态地添加不同的配料(如牛奶和糖)。

4.1 组件接口

// Java实现
public interface Coffee {
    double cost();
    String getDescription();
}

4.2 具体组件

public class SimpleCoffee implements Coffee {
    public double cost() {
        return 5.0;
    }
    
    public String getDescription() {
        return "Simple Coffee";
    }
}

4.3 装饰者抽象类

public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
    
    public double cost() {
        return coffee.cost();
    }
    
    public String getDescription() {
        return coffee.getDescription();
    }
}

4.4 具体装饰者

public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    public double cost() {
        return super.cost() + 1.5;
    }
    
    public String getDescription() {
        return super.getDescription() + ", Milk";
    }
}

public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    public double cost() {
        return super.cost() + 0.5;
    }
    
    public String getDescription() {
        return super.getDescription() + ", Sugar";
    }
}

4.5 使用装饰者模式

public class CoffeeShop {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());

        coffee = new MilkDecorator(coffee);
        System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());

        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());
    }
}

4.6 输出结果:

Simple Coffee Cost: $5.0
Simple Coffee, Milk Cost: $6.5
Simple Coffee, Milk, Sugar Cost: $7.0

五、 应用场景

在这里插入图片描述

5.1 图形用户界面


  在图形用户界面(GUI)框架中,装饰者模式广泛应用于实现各种控件的装饰功能。控件如按钮、文本框等可以用不同的装饰者类装饰来添加多种新功能,如滚动条、边框等。例如,Java Swing框架中的JComponent类就是使用类似装饰者模式的理念实现的。

5.2 数据流处理


  在数据流处理框架中,输入输出流是装饰者模式的另一个经典应用。JavaI/O流设计就是实现装饰者模式的一个优秀示例,如FileInputStreamBufferedInputStreamDataInputStream等通过装饰者模式组合,实现了灵活而强大的数据流操作功能。

5.3 日志功能


  日志记录功能的实现也是装饰者模式的理想应用场景。例如,传统的日志记录器Logger可以通过装饰者模式添加不同的日志处理和记录策略,如格式化日志、输出到文件、发送电子邮件等。

5.4 监控和计数


  在监控系统中,可以动态地为程序添加计数器、性能监控器等功能,以增强对系统运行状态的了解。

六、总结

  装饰者模式是一种强大的设计模式,它提供了一种灵活、可扩展的方式来动态地为对象添加新功能。通过这一模式,我们可以在不修改已有类代码的情况下,灵活地扩展系统功能,符合开闭原则单一职责原则。无论是在GUI编程中、日志功能增强,还是在数据流处理以及监控系统中,装饰者模式都能发挥重要作用。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式Linux系统编程 — 6.2 signal和 sigaction信号处理函数

目录 1 信号如何处理 2 signal()函数 2.1 signal()函数介绍 2.2 示例程序 3 sigaction()函数 3.1 sigaction()函数介绍 3.2 示例程序 1 信号如何处理 信号通常是发送给对应的进程,当信号到达后, 该进程需要做出相应的处理措施,可以通…

ROS——Server、Client的编程实现,服务数据的定义与使用,参数的使用和编程方法

客户端 创建功能包 创建客户端、创建服务、配置请求数据、请求调用、等待应答 设置编译规则 编译运行客户端 服务端 创建服务器 编译成目标执行文件、相关库的连接 add_executable(turtle_command_server src/turtle_command_server.cpp) target_link_libraries(turtle_comman…

第2章 寄存器

第2章 寄存器 一个 CPU 由运算器,控制器,寄存器等器件构成,这些器件靠内部总线进行相连。简单的说 CPU 中: 运算器进行信息处理寄存器进行信息存储控制器控制各种器件进行工作内部总线连接各个器件,在他们之间进行各种…

工业交换机端口统计功能

工业交换机端口统计功能不仅是一项技术手段,更是一双透视企业网络健康状态的慧眼。通过这一功能,企业能够实时捕捉到网络中每一个端口的流量情况,这不仅仅是数据的积累,更是对网络脉搏的精准把握。当网络的每一个脉动都被记录在案…

git基本使用(一):git的基本概念

Git 是一种分布式版本控制系统,最初由 Linus Torvalds 于 2005 年为 Linux 内核开发。它主要用于跟踪文件的更改,特别是在软件开发过程中,可以帮助团队成员协同工作。它在实际项目开发中,应用非常广泛,我们这一节来掌握…

第2章.现场设备的物联网模式--设备管理

2.3 设备管理 设备的作用及其管理方式是物联网和非物联网部署之间的关键区别。设备生命周期管理的阶段包括设备供应(注册、激活和调试)到取消供应。本书中用于设备管理的注释如下图所示: 图2.6——设备管理模式的符号 设备管理包括现场设备的…

Power Platform功能管理实战课程重点学什么?怎么学?

Power Platform 由 Power BI、Power Apps、Power Automate、Power Virtual Agents 四大模块组成。 这几个模块单独应用都具有强大的功能,而微软把它们放在一起,相互协作、相得益彰,形成了强大的生态系统。而这也是Power Platform的核心理念—…

Java案例实现双色球

一问题&#xff1a; 二具体代码&#xff1a; package 重修;import java.util.Random; import java.util.Scanner;public class first {public static void main(String[] args) {int []usersnumbersusernumslect();System.out.println("用户");for (int i 0; i <…

springboot个人证书管理系统-计算机毕业设计源码16679

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了个人证书管理系统的开发全过程。通过分析个人证书管理系统管理的不足&#xff0c;创建了一个计算机管理个人证书管理系统的方案。文章介绍了个人证书管理系统的系…

计算机系统基础(二)

1.数值数据的表示 为什么采用二进制&#xff1f; 二进制只有两种基本状态&#xff0c;两个物理器件就可以表示0和1二进制的编码、技术、运算规则都很简单0和1与逻辑命题的真假对应&#xff0c;方便通过逻辑门电路实现算术运算 数值数据表示的三要素 进位记数制&#xff08;十…

开发数字药店APP实战:互联网医院系统源码详解

本篇文章&#xff0c;笔者将深入探讨如何开发一个功能完善的数字药店APP&#xff0c;并详细解析互联网医院系统的源码实现。 一、数字药店APP的需求分析 应具备以下基本功能&#xff1a; 用户注册与登录 药品搜索与浏览 在线下单与支付 订单管理 健康咨询与远程医疗 个人…

发电机保护屏组成都有哪些,如何选择

发电机保护屏组成都有哪些&#xff0c;如何选择 发电机是电力系统中最常用的一种电力设备。例如水力发电机&#xff0c;柴油发电机&#xff0c;风力发电机&#xff0c;火力发电等等。发电机保护是保证发电机安全、稳定运行的重要手段之一。对于一些小型机组的发电机&#xff0c…

Mysql部署MHA高可用

部署前准备&#xff1a; mysql-8.0.27下载地址&#xff1a;https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar mha-manager下载地址&#xff1a;https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-mana…

因为自己淋过雨所以想给嵌入式撑把伞

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;新手学嵌入式&#xff0c;…

PHP验证日本固定电话号码

日本电话号码格式众多&#xff0c;验证起来比较头大&#xff0c;现在咱们来一个简单的总结哈 为了简单起见&#xff0c;使用PCRE 函数preg_match通过匹配正则表达式来实现验证。 function checkGdTelLandline(string $str): int|false {return preg_match("/\A0(\d{1}[-…

积鼎CFD:基于Virtualflow在溃坝洪水演进数值仿真分析

近期&#xff0c;多地遭受了前所未有的洪水侵袭&#xff0c;每一次灾害都如同警钟长鸣&#xff0c;提醒我们水库大坝安全的重要性&#xff0c;超标准暴雨的突袭让大坝的安全防线面临前所未有的考验。面对这一挑战&#xff0c;CFD技术可为溃坝洪水的预测与管理开辟新的路径。凭借…

python+django 环境搭建以及post接口封装

1、搭建pythondjango环境 python 3.7.9的版本 具体参考之前的安装教程 django 使用 pip install django 会自动安装 检验安装版本&#xff1a; python -m django --version 2、创建django项目 django-admin startproject projectname 启动项目&#xff1a;python manage.py…

基于X86+FPGA+AI的切割机控制、六轴机器人控制方案

一、智能设备控制 应用场景 智能制造(Intelligent Manufacturing, IM)是一种由智能机器和人类专家共同组成的人机一体化智能系统&#xff0c;它在制造过程中能进行智能活动&#xff0c;诸如分析、推理、判断、构思和决策等。通过人与智能机器的合作共事&#xff0c;去扩大、延…

力扣 用队列实现栈(Java)

核心思想&#xff1a;因为队列都是一端进入另一端出&#xff08;先进先出&#xff0c;后进后出&#xff09;&#xff0c;因此一个队列肯定是不能实现栈的功能的&#xff0c;这里就创建两个队列来模拟栈的先进后出&#xff0c;后进先出。 比如说如果是push操作我们肯定是要弹出栈…

用四个场景案例,分析使用大模型对程序员工作的帮助提升_大模型应用场景

引言 随着人工智能技术的不断发展&#xff0c;大模型在软件开发中的应用越来越广泛。 这些大模型&#xff0c;如GPT、文心一言、讯飞星火、盘古大模型等&#xff0c;可以帮助程序员提高工作效率&#xff0c;加快开发速度&#xff0c;并提供更好的用户体验。 本文将介绍我在实…