装饰器模式(Decorator)

news2024/9/20 14:41:55

装饰器模式是一种结构型设计模式,用来动态地给一个对象增加一些额外的职责。就增加对象功能来说,装饰器模式比生成子类实现更为灵活。装饰器模式的别名为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。

Decorator is a structural design pattern, that can be used to dynamically add some additional responsibilities to an
 object. In terms of adding object functionality, the decorator pattern is more flexible than generating subclass 
 implementations. The alias for the decorator pattern is "wrapper", which is the same as the alias for the adapter 
 pattern, but they are suitable for different situations.  

结构设计

装饰器模式包含如下角色:
Component: 抽象构件,定义一个对象接口,用来动态地给一个对象增加一些额外的职责
ConcreteComponent: 具体构件,实现一个对象接口
Decorator: 抽象装饰类,拥有一个指向被封装对象的引用成员变量。装饰类会将所有操作委派给被封装的对象。
ConcreteDecorator: 具体装饰类,定义了可动态添加到抽象构件的具体行为。具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为。
装饰器模式类图表示如下:
请添加图片描述

伪代码实现

接下来将使用代码介绍下装饰器模式的实现。

// 1、抽象构件,定义一个对象接口,用来动态地给一个对象增加一些额外的职责
public interface Component {
    void operation();
}
// 2、具体构件,实现一个对象接口
public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("do some thing in the concrete component instance");
    }
}
// 3、抽象装饰类,拥有一个指向被封装对象的引用成员变量。装饰类会将所有操作委派给被封装的对象  
public class Decorator implements Component {
    private Component component = null;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        this.component.operation();
    }
}
// 4、具体装饰类,定义了可动态添加到抽象构件的具体行为。具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        afterOperation();
    }

    private void afterOperation() {
        System.out.printf("do some thing after operation in the concrete decorator");
    }
}
// 5、客户端调用
public class DecoratorClient {
    public void test() {
        // (1) 声明接口并实例化组件
        Component component = new ConcreteComponent();
        // (2) 调用组件方法(装饰前)
        component.operation();
        // (3) 实例化具体装饰器并对组件进行装饰
        component = new ConcreteDecorator(component);
        // (4) 调用组件方法(装饰后)
        component.operation();
    }
}

适用场景

在以下情况可以考虑使用装饰器模式:
(1) 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
(2) 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
装饰器能将业务逻辑组织为层次结构,开发者可为各层创建一个装饰,在运行时将各种不同逻辑组合成对象。由于这些对象都遵循通用接口,客户端代码能以相同的方式使用这些对象。
(3) 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类)
说明:一般有两种方式可以实现给一个类或对象增加行为:
(1) 继承机制,使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。
(2) 关联机制,即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机。

优缺点

装饰器模式有以下优点:
(1) 符合开闭原则。具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
(2) 符合单一职责原则。开发者可以将实现了许多不同行为的一个大类拆分为多个较小的类。
(3) 提高了代码的可扩展性和灵活性。装饰器模式与继承关系的目的都是要扩展对象的功能,但是装饰器模式可以提供比继承更多的灵活性,可以在不创建新子类的前提下,扩展对象的行为。
(4) 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
(5) 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
但是装饰器模式也存在以下缺点:
(1) 代码复杂度上升。使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
(2) 装饰器模式比继承更加灵活,也同时意味着装饰器模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

参考

《设计模式:可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著 李英军, 马晓星 等译
https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/decorator.html 装饰器模式
https://refactoringguru.cn/design-patterns/decorator 装饰器模式
https://www.runoob.com/design-pattern/decorator-pattern.html 装饰器模式
https://www.cnblogs.com/adamjwh/p/9036358.html 简说设计模式——装饰模式
https://blog.csdn.net/ShuSheng0007/article/details/88780036 秒懂设计模式之装饰者模式

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

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

相关文章

P1219 [USACO1.5] 八皇后 Checker Challenge

题目 思路 非常经典的dfs题&#xff0c;需要一点点的剪枝 剪枝①&#xff1a;行、列&#xff0c;对角线的标记 剪枝②&#xff1a;记录每个皇后位置 代码 #include<bits/stdc.h> using namespace std; const int maxn105; int a[maxn];int n,ans; bool vis1[maxn],vis…

如何使用无线通信设备实现室内外精准定位管理?

巡更功能的意义 电子巡更系统的建立&#xff0c;使巡逻安防工作更加科学合理&#xff0c;使安全管理更加规范化、标准化制度化。例如&#xff0c;当管理人员设置巡更线路&#xff0c;在巡更线路上设置巡更点&#xff0c;通过巡更管理系为巡更人员排班在巡更区域内形成了一张防范…

《Java-SE-第二十三章》之单例模式

文章目录 单例模式概述饿汉模式懒汉模式单线程版懒汉单例多线程版枚举实现单例 单例模式概述 单例模式是设计模式中的一种,其作用能保证某个类在程序中只存在唯一一份实例,而不会创建多份实例。单例模式具体的实现方式, 分成 “饿汉” 和 “懒汉” 两种.。饿汉模式中的饿不并不…

R语言【Tidyverse、Tidymodel】的机器学习方法

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”&#xff0c;是发现新规律&#xff0c;总结和分析实验结果的利器。机器学习涉及的理论和方法繁多&#xff0c;编程相当复杂&#xff0c;一直是阻碍机器学习大范围应用的主要困难之一&#xff0c;由此诞生了Python…

深入浅出对话系统——大规模开放域对话模型PLATO

引言 今天主要介绍百度退出的大模型开放领域对话模型PLATO的三篇论文&#xff0c;分别对应三个模型。 PLATO 132M parameters8M samples问题&#xff1a;训练稳定性和效率 PLATO-2 1.6B, 314M and 93M parameters684M samples PLATO-XL 11B parameters811M samples for en1.2…

JavaWeb(8)——前端综合案例2(节流和防抖)

目录 一、节流和防抖概念 二、实例演示 三、需要注意的 一、节流和防抖概念 二、实例演示 Lodash 简介 | Lodash中文文档 | Lodash中文网 (lodashjs.com) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><m…

vivo传便签数据到OPPO新手机上怎么操作

一般来说&#xff0c;一台手机在使用了三年之后&#xff0c;就容易出现各种各样的问题&#xff0c;这时候就需要考虑换手机了。而在更换手机的时候&#xff0c;有相当一部分消费者都会选择更换与旧手机不同品牌的手机使用&#xff0c;例如之前使用的手机是vivo的&#xff0c;现…

【云原生-制品管理】制品管理的优势

制品介绍制品管理-DevOps制品管理优势总结 制品介绍 制品管理指的是存储、版本控制和跟踪在软件开发过程中产生的二进制文件或“制品”的过程。这些制品可以包括编译后的源代码、库和文档&#xff0c;包括操作包、NPM 和 Maven 包&#xff08;或像 Docker 这样的容器镜像&…

Adobe Camera Raw 常用快捷键

戳下方链接&#xff0c;后台回复“230707PS插件”获取相关插件应用 回复“230708PS插件教程”获取教学链接; 回复“230730camera快捷键”获取快捷键链接。 原文链接&#xff1a;https://mp.weixin.qq.com/s/tVNDBPUtKrUtfGmPKJ0Tdw 目标调整工具 作用WindowsmacOS选取目标调整工…

WilliamNing - 电脑办公环境 - 以及个人工作/开发习惯 - Windows/Mac

主要是记录个人的办公环境习惯&#xff0c;方便到新的环境&#xff0c;快速搭建自己熟悉的环境&#xff0c;从而提高工作效率 1. Windows 深圳客友 腾讯外包 家里电脑 TBD 2. Mac SeekAsia[深圳就业网络] Kumu[成都脑海科技] 2.1 桌面软件列表 后调整 -- 加了一些软件 同时…

轻松构建全栈观测,从容应对咖啡产业竞争

1964 年&#xff0c;Tim Hortons 咖啡馆诞生于多伦多的宁静小镇汉密尔顿&#xff0c;由传奇冰球运动员 Tim Horton 先生创立。经过近 60 年的发展&#xff0c;Tim Hortons 已成为全球著名咖啡连锁品牌。在英国权威品牌评估机构 Brand Finance 发布的“全球最有价值的 25 个餐厅…

KVM创建新的虚拟机(图形化)

1.启动kvm管理器 [rootlocalhost ~]# virt-manager2.点击创建虚拟机 3.选择所需os安装镜像 4.选择合适的内存大小和CPU 5.创建所需磁盘 6.命名创建的虚拟机

C#界面美化小技巧

1.窗体设置为无边框 FormBorderStyle的属性设置为none 2.窗体无边框&#xff0c;可以拖拽 private Point mPoint new Point(); private void Download_MouseDown(object sender, MouseEventArgs e) { mPoint.X e.X; mPoint.Y e.Y; …

Vue3--->组合式API与Pinia

目录 使用create-vue搭建 1、使用create-vue创建项目 2、项目目录和关键文件 组合式API 1、组合式API - setup选项 2、组合式API - reactive和ref函数 3、组合式API - computed 4、组合式API - watch 1、基础使用 - 侦听单个数据 2、基础使用 - 侦听多个数据 3、immediate&…

面向对象学生考试系统实战:用Java构建简单的学生考试系统(附源码)

文章目录 项目简介项目代码实现1. Person类2. Student类3. Teacher类4. Question类5. ExamMachine类6. TestMain类&#xff08;主程序&#xff09; 项目运行 在当今科技高速发展的时代&#xff0c;面向对象编程成为了软件开发的主流范式之一。通过面向对象的方法&#xff0c;我…

【CSDN】

欢迎使用Mark编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持&#xff0c…

著名开源Linux图形驱动开发者与Valve签约

导读据报道&#xff0c;Valve 最近聘用了著名开源 Linux 图形驱动开发者 Alyssa Rosenzweig&#xff0c;以改进开源 Linux 图形驱动程序堆栈&#xff0c;增强 Linux 游戏生态系统。 据报道&#xff0c;Valve 最近聘用了著名开源 Linux 图形驱动开发者 Alyssa Rosenzweig&#…

国家留学基金委(CSC)|发布2024年创新型人才国际合作培养项目实施办法

2023年7月28日&#xff0c;国家留学基金委&#xff08;CSC&#xff09;发布了《2024年创新型人才国际合作培养项目实施办法》&#xff0c;在此知识人网小编做全文转载。详细信息请参见https://www.csc.edu.cn/chuguo/s/2648。 2024年创新型人才国际合作培养项目实施办法 第一章…

工作中用到的shell命令

工作中用到的shell命令 1、查看自己的系统版本:2、登陆远程服务第一种情况&#xff08;没做端口映射&#xff09;&#xff1a;第二种情况&#xff08;做了端口映射&#xff09;&#xff1a; 3、 ls -l -f4、grep5、scp6、zip 7、标准输入输出8、dirname9、date 1、查看自己的系…

基于微信机器人的二次开发

使用微信ipad协议来开发微信机器人&#xff0c;可以开发的项目很多&#xff0c;例如一些娱乐机器人、云发单系统&#xff0c;私域流量的智能管理和营销拓客&#xff0c;还有一些自动采集和发朋友圈的云端系统等。每个行业都有需求这样的系统应用&#xff0c;在线教育、金融、电…