设计模式之 装饰者模式

news2024/11/22 21:31:49

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许通过动态地给对象添加额外的功能,而不需要修改对象的结构。装饰者模式通过创建一个装饰类来封装原始对象,并为原始对象提供附加的功能。这种模式使得我们能够在运行时扩展对象的功能,避免了继承的局限性。

装饰者模式的核心思想是在不改变对象自身的情况下,给对象添加额外的职责。通过使用装饰者,可以使得对象的功能变得更加灵活,可以根据需要动态地添加功能。

一、装饰者模式的结构

装饰者模式的结构通常包括以下几个角色:

  1. 组件接口(Component)

    这是一个抽象的接口或类,它定义了被装饰的对象的基本功能。所有的具体组件(ConcreteComponent)和装饰者(Decorator)都需要实现或继承该接口。
  2. 具体组件(ConcreteComponent)

    具体组件是装饰者模式中的核心类,它实现了组件接口,并定义了具体的功能。它是被装饰的对象。
  3. 装饰者(Decorator)

    装饰者类是一个抽象类,它也实现了组件接口,并持有一个组件对象的引用。它的主要作用是通过在方法中调用组件对象的方法,然后再为其添加新的功能。
  4. 具体装饰者(ConcreteDecorator)

    具体装饰者是装饰者的子类,它在装饰者类的基础上,提供附加功能的实现。通过具体装饰者,可以实现不同的装饰功能。

二、装饰者模式的工作原理

装饰者模式的基本工作原理是:通过将一个组件(具体对象)传递给装饰者类,并通过装饰者来扩展其功能。装饰者类通常会持有一个指向组件接口的引用,这样就可以在不改变原有类的情况下,通过装饰者对象动态添加额外的功能。

装饰者模式可以理解为“在现有对象的外层包裹一个新的类”,通过组合的方式,而不是继承的方式,来扩展对象的功能。

三、装饰者模式的示例

示例:咖啡店

在咖啡店的业务中,我们可能需要为每一杯咖啡添加不同的配料(如牛奶、糖等)。我们可以使用装饰者模式来实现这个需求。

  • 抽象咖啡(组件接口)
    public class Coffee {
    
        private double price;
        private String desc;//描述
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    
        public Coffee() {
    
        }
    
        public Coffee(double price, String desc) {
            this.price = price;
            this.desc = desc;
        }
    }
  • 具体咖啡(具体组件)
    public class Americano extends Coffee{
        public Americano() {
            super(10,"美式咖啡");
        }
    }
    public class Latte extends Coffee{
        public Latte() {
            super(8, "拿铁咖啡");
        }
    }
  •  装饰者类
    public class Decorator extends Coffee{
        private Coffee coffee;
    
        public Coffee getCoffee() {
            return coffee;
        }
    
        public void setCoffee(Coffee coffee) {
            this.coffee = coffee;
        }
    
        public Decorator(double price, String desc, Coffee coffee) {
            super(price, desc);
            this.coffee = coffee;
        }
    }
    
  •  具体装饰者(加糖,加奶)
    public class Sugar extends Decorator {
        public Sugar(Coffee coffee){
            super(1,"加糖",coffee);
        }
    
        @Override
        public double getPrice() {
            return getCoffee().getPrice() + super.getPrice();
        }
    
        @Override
        public String getDesc() {
            return getCoffee().getDesc() + super.getDesc();
        }
    }
    
    public class Milk extends Decorator{
        public Milk(Coffee coffee) {
            super(2, "加奶", coffee);
        }
        @Override
        public double getPrice() {
            return getCoffee().getPrice() + super.getPrice();
        }
    
        @Override
        public String getDesc() {
            return getCoffee().getDesc() + super.getDesc();
        }
    }
  •  测试类
    public class Client {
        public static void main(String[] args) {
            Coffee coffee = new Americano();
            System.out.println(coffee.getDesc() + ": " + coffee.getPrice());
    
            coffee = new Sugar(coffee);
            System.out.println(coffee.getDesc() + ": " + coffee.getPrice());
    
            coffee = new Milk(coffee);
            System.out.println(coffee.getDesc() + ": " + coffee.getPrice());
        }
    }
  •  运行结果
 
解释
  • Coffee是一个基础的咖啡类,定义了咖啡的基础属性
  • Decorator是装饰者类,它包装了一个Coffee对象
  • MilkSugar是具体装饰者类,它们分别为咖啡添加了牛奶和糖的费用。
  • 客户端可以选择性地给咖啡添加不同的装饰(例如,先加牛奶,再加糖),而且这些装饰类可以按需组合。

四、装饰者模式的优缺点

优点:
  1. 更灵活的扩展功能:

    • 装饰者模式可以在不修改原始类的情况下,动态地给对象添加新功能,从而增加了系统的灵活性。
  2. 避免了类的爆炸性增长:

    • 使用装饰者模式可以避免过多的继承层次结构,如果使用继承的话,会导致类的数量急剧增加。而通过装饰者,可以根据需要动态添加功能,保持系统结构的简洁性。
  3. 支持对象的职责分离:

    • 每个装饰者负责提供一个具体的功能,可以使得不同的功能职责分离,避免单一类承担过多的责任。
  4. 符合开闭原则:

    • 装饰者模式遵循了开闭原则,即对扩展开放,对修改封闭。通过装饰器,我们可以在不修改原始代码的情况下为对象添加新功能。
缺点:
  1. 增加了系统复杂度:

    • 由于使用了多个装饰类,可能会导致系统中装饰类的数量过多,增加了管理和理解的难度。
  2. 可能会使得代码变得难以追踪:

    • 因为装饰者会包裹原始对象并改变其行为,过多的装饰者链可能使得程序的行为变得难以理解和调试。
  3. 性能开销:

    • 每增加一个装饰者,都会增加一次方法调用的开销。如果装饰链很长,可能会影响性能。

五、装饰者模式的应用场景

装饰者模式适用于以下几种场景:

  1. 需要动态地为对象添加功能时:

    • 如果一个类需要动态地增加一些附加功能,而不是通过继承来实现,装饰者模式是一个很好的选择。
  2. 避免类的爆炸性增长:

    • 如果通过继承的方式去增加功能,会导致类的数量激增。使用装饰者模式,可以避免这种问题,并保持代码的简洁性。
  3. 功能可以独立扩展:

    • 如果对象的功能是可以独立扩展的,可以使用装饰者模式。在每个装饰类中,只负责某个特定功能的增强。
  4. 允许客户端按需增加功能:

    • 如果希望用户可以选择性地为对象增加某些功能,可以使用装饰者模式。每个装饰者都可以单独工作,也可以组合使用。

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

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

相关文章

大数据调度组件之Apache DolphinScheduler

Apache DolphinScheduler 是一个分布式易扩展的可视化 DAG 工作流任务调度系统。致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用。 主要特性 易于部署,提供四种部署方式,包括Standalone、Cluster、Docker和…

ThinkPHP6门面(Facade)

门面 门面(Facade) 门面为容器中的(动态)类提供了一个静态调用接口,相比于传统的静态方法调用, 带来了更好的可测试性和扩展性,你可以为任何的非静态类库定义一个facade类。 系统已经为大部分…

MySQL win安装 和 pymysql使用示例

目录 一、MySQL安装 下载压缩包: 编写配置文件: 配置环境变量: 初始化服务和账户 关闭mysql开机自启(可选) 建议找一个数据库可视化软件 二、使用pymysql操作数据库 安装pymysql 示例代码 报错处理 一、My…

Parker派克防爆电机在实际应用中的安全性能如何保证?

Parker防爆电机确保在实际应用中的安全性能主要通过以下几个方面来保证: 1.防爆外壳设计:EX系列电机采用强大的防爆外壳,设计遵循严格的防爆标准,能够承受内部可能发生的爆炸而不破损,利用间隙切断原理,防…

空间与单细胞转录组学的整合定位肾损伤中上皮细胞与免疫细胞的相互作用

result 在空间转录组图谱中对人类肾脏进行无监督映射和细胞类型鉴定 我们试图在H&E染色的人类参考肾切除标本组织切片上直接映射转录组特征。该组织来自一名59岁的女性,其肾小球闭塞和间质纤维化程度最低(分别影响不到10%的肾小球或肾实质&#xff…

greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用

简略图 greater<>()(a, b) a > b 返回true&#xff0c;反之返回false less<>()(a, b) a < b 返回true&#xff0c;反之返回false 在cmp中使用&#xff08;正着理解&#xff09; 规则返回true时a在前&#xff0c;反之b在前 在priority_queue中使用 &#xff…

详细描述一下Elasticsearch索引文档的过程?

大家好&#xff0c;我是锋哥。今天分享关于【详细描述一下Elasticsearch索引文档的过程&#xff1f;】面试题。希望对大家有帮助&#xff1b; 详细描述一下Elasticsearch索引文档的过程&#xff1f; Elasticsearch的索引文档过程是其核心功能之一&#xff0c;涉及将数据存储到…

入门车载以太网(6) -- XCP on Ethernet

目录 1.寻址方式 2.数据帧格式 3.特殊指令 4.使用实例 了解了SOME/IP之后&#xff0c;继续来看看车载以太网在汽车标定领域的应用。 在汽车标定领域XCP是非常重要的协议&#xff0c;咱们先来回顾下基础概念。 XCP全称Universal Measurement and Calibration Protocol&a…

Python中常用的函数介绍

Python中常用的几种函数 1、input函数 input()函数&#xff1a;主要作用是让用户输入某个内容并接收它。 #输入你的年龄 >>> age input("my age is :") my age is :20 执行代码后输入年龄&#xff0c;年龄被存放到age变量中&#xff0c;执行print后终端会…

Ubuntu从入门到精通(二)远程和镜像源配置齐全

Ubuntu从入门到精通(二) 1 常见操作配置 1.1 英文语言配置 1.1.1 打开设置 1.1.2 设置语言为英文 1.1.3 重启生效 1.1.4 再次进入,选择更新名字 1.1.5 再次进入,发现已经变成了英文 1.2 输入法配置 1.3 rustdesk安装 1.3.1 Windows系统配置 登陆:https://github.com…

卷积神经网络(CNN)中的池化层(Pooling Layer)

池化层&#xff08;Pooling Layer&#xff09;&#xff0c;也被称为下采样层&#xff0c;是深度学习神经网络中常用的一种层级结构。它通常紧跟在卷积层之后&#xff0c;对卷积层输出的特征图进行下采样操作。 一、定义与功能 池化层的主要作用是通过减少特征图的尺寸来降低计算…

【linux硬件操作系统】计算机硬件常见硬件故障处理

这里写目录标题 一、故障排错的基本原则二、硬件维护注意事项三、关于最小化和还原出厂配置四、常见故障处理及调试五、硬盘相关故障六、硬盘相关故障&#xff1a;硬盘检测问题七、硬盘相关故障&#xff1a;自检硬盘报错八、硬盘相关故障&#xff1a;硬盘亮红灯九、硬盘相关故障…

《操作系统》实验内容 实验二 编程实现进程(线程)同步和互斥(Python 与 PyQt5 实现)

实验内容 实验二 编程实现进程&#xff08;线程&#xff09;同步和互斥 1&#xff0e;实验的目的 &#xff08;1&#xff09;通过编写程序实现进程同步和互斥&#xff0c;使学生掌握有关进程&#xff08;线程&#xff09;同步与互斥的原理&#xff0c;以及解决进程&#xf…

智慧路面管理系统平台 智慧照明 智慧市政 智慧交通

智慧路面管理系统平台   智慧路面管理系统平台&#xff0c;旨在提高城市道路的智能化水平和交通效率。该系统通过集成传感器、摄像头、监控设备、大数据、云计算等多种技术手段&#xff0c;实现对道路状况和交通流量的实时监测与分析&#xff0c;从而提供精准的交通数据和智能…

数据结构 ——— 判断一棵树是否是完全二叉树

目录 满二叉树和完全二叉树示意图 手搓一个完全二叉树 代码实现 满二叉树和完全二叉树示意图 注意区分满二叉树和完全二叉树 满二叉树的每一层都是满的&#xff0c;也就是除了叶子节点&#xff0c;其他节点都有左右节点 完全二叉树的最后一层不一定是满的&#xff0c;但是从…

Vue_Router权限控制:不同角色显示不同路由

写在前面 在Vue中&#xff0c;Router是一个官方提供的用于处理应用程序路由的插件。它允许我们创建单页应用程序&#xff08;SPA&#xff09;&#xff0c;其中不同的页面和组件可以通过URL进行导航和展示。使我们可以轻松地创SPA&#xff0c;并实现可复用和可组合的组件…

java多线程并发执行方法或者调用接口

在开发过程中有时需要检查某个接口或者某个方法是否存在并发安全问题&#xff0c;我们会用到jmeter 、AB 等压测工具辅助我们完成代码测试&#xff0c;虽然这些工具功能很强大&#xff0c;也很好用&#xff0c;但是在开发过程中来使用还是不如直接执行Test 或者main 方法来的方…

Python小游戏28——水果忍者

首先&#xff0c;你需要安装Pygame库。如果你还没有安装&#xff0c;可以使用以下命令进行安装&#xff1a; 【bash】 pip install pygame 《水果忍者》游戏代码&#xff1a; 【python】 import pygame import random import sys # 初始化Pygame pygame.init() # 设置屏幕尺寸 …

测评部署和管理 WordPress 最方便的面板

新版宝塔面板快速搭建WordPress新手教程 - 倚栏听风-Morii - 博客园 初学者使用1Panel面板快速搭建WordPress网站 - 倚栏听风-Morii - 博客园 可以看到&#xff0c;无论是宝塔还是1Panel&#xff0c;部署和管理WordPress都有些繁琐&#xff0c;而且还需要额外去配置Nginx和M…

OpenAI Adjusts Strategy as ‘GPT’ AI Progress Slow

注&#xff1a;本文为两篇关于当前大模型方向讨论的文章。 OpenAI 大改下代大模型方向&#xff0c;scaling law 撞墙&#xff1f;AI 社区炸锅了 机器之心 2024 年 11 月 11 日 11:57 北京 机器之心报道 编辑&#xff1a;Panda、泽南 大模型的 scaling law 到头了&#xff1f…