设计模式-结构型模式之装饰模式

news2025/4/8 6:45:30

3. 装饰模式

3.1. 模式动机

一般有两种方式可以实现给一个类或对象增加行为:

  • 继承机制

使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。
  • 关联机制

即将一个类的对象嵌入另一个对象中,由另一个对象来决定是否调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰器(Decorator)
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。这就是装饰模式的模式动机。

3.2. 模式定义

装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式

3.3. 模式结构

装饰模式包含如下角色:

  • Component: 抽象构件

  • ConcreteComponent: 具体构件

  • Decorator: 抽象装饰类

  • ConcreteDecorator: 具体装饰类

3.4. 时序图

3.5. 代码分析

///
//  ConcreteComponent.cpp
//  Implementation of the Class ConcreteComponent
//  Created on:      03-十月-2014 18:53:00
//  Original author: colin
///

#include "ConcreteComponent.h"
#include <iostream>
using namespace std;


ConcreteComponent::ConcreteComponent(){

}

ConcreteComponent::~ConcreteComponent(){

}

void ConcreteComponent::operation(){
    cout << "ConcreteComponent's normal operation!" << endl;
}
///
//  ConcreteDecoratorA.h
//  Implementation of the Class ConcreteDecoratorA
//  Created on:      03-十月-2014 18:53:00
//  Original author: colin
///

#if !defined(EA_6786B68E_DCE4_44c4_B26D_812F0B3C0382__INCLUDED_)
#define EA_6786B68E_DCE4_44c4_B26D_812F0B3C0382__INCLUDED_

#include "Decorator.h"
#include "Component.h"

class ConcreteDecoratorA : public Decorator
{

public:
    ConcreteDecoratorA(Component* pcmp);
    virtual ~ConcreteDecoratorA();

    void addBehavior();
    virtual void operation();

};
#endif // !defined(EA_6786B68E_DCE4_44c4_B26D_812F0B3C0382__INCLUDED_)
///
//  ConcreteDecoratorA.cpp
//  Implementation of the Class ConcreteDecoratorA
//  Created on:      03-十月-2014 18:53:00
//  Original author: colin
///

#include "ConcreteDecoratorA.h"
#include <iostream>
using namespace std;

ConcreteDecoratorA::ConcreteDecoratorA(Component* pcmp)
:Decorator(pcmp)
{

}

ConcreteDecoratorA::~ConcreteDecoratorA(){

}

void ConcreteDecoratorA::addBehavior(){
    cout << "addBehavior AAAA" << endl;
}


void ConcreteDecoratorA::operation(){
    Decorator::operation();
    

运行结果:

3.6. 模式分析

  • 与继承关系相比,关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关系,无法在程序运行时动态扩展。在软件开发阶段,关联关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于关联关系使系统具有较好的松耦合性,因此使得系统更加容易维护。当然,关联关系的缺点是比继承关系要创建更多的对象。

  • 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。

3.7. 实例

实例:变形金刚

变形金刚在变形之前是一辆汽车,它可以在陆地上移动。当它变成机器人之后除了能够在陆地上移动之外,还可以说话;如果需要,它还可以变成飞机,除了在陆地上移动还可以在天空中飞翔。

3.8. 优点

  • 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性

  • 可以通过一种动态的方式来扩展个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。

  • 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

  • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则

3.9. 缺点

  • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度加大学习与理解的难度

  • 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

3.10. 适用环境

在以下情况下可以使用装饰模式:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。

  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类).

3.11. 模式扩展

装饰模式的简化-需要注意的问题:

  • 一个装饰类的接口必须与被装饰类的接口保持相同,对于客户端来说无论是装饰之前的对象还是装饰之后的对象都可以一致对待。

  • 尽量保持具体构件类Component作为一个“轻”类,也就是说不要把太多的逻辑和状态放在具体构件类中,可以通过装饰类对其进行扩展。

  • 如果只有一个具体构件类而没有抽象构件类,那么抽象装饰类可以作为具体构件类的直接子类。

3.12. 总结

  • 装饰模式用于动态地给一个对象增加一些额外的职责,就增加对象功 能来说,装饰模式比生成子类实现更为灵活。它是一种对象结构型模式

  • 装饰模式包含四个角色抽象构件定义了对象的接口,可以给这些对 象动态增加职责(方法);具体构件定义了具体的构件对象,实现了 在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法); 抽象装饰类是抽象构件类的子类,用于给具体构件增加职责,但是具 体职责在其子类中实现;具体装饰类是抽象装饰类的子类,负责向构 件添加新的职责。

  • 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动 态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子 类的情况下,将对象的功能加以扩展。

  • 装饰模式的主要优点在于可以提供比继承更多的灵活性,可以通过一种动态的 方式来扩展一个对象的功能,并通过使用不同的具体装饰类以及这些装饰类的 排列组合,可以创造出很多不同行为的组合,而且具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类;其主要缺点在于使用装饰模式进行系统设计时将产生很多小对象,而且装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需 要逐级排查,较为烦琐。

  • 装饰模式适用情况包括:在不影响其他对象的情况下,以动态、透明的方式给 单个对象添加职责;需要动态地给一个对象增加功能,这些功能也可以动态地 被撤销;当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展 和维护时。

  • 装饰模式可分为透明装饰模式半透明装饰模式:在透明装饰模式中,要求客 户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该声明具体构 件类型和具体装饰类型,而应该全部声明为抽象构件类型;半透明装饰模式允 许用户在客户端声明具体装饰者类型的对象,调用在具体装饰者中新增的方法。

[上一节]设计模式-结构型模式之桥接模式

[下一节]设计模式-结构型模式之外观模式

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

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

相关文章

CSS基础——盒子模型

目录 简介 盒子模型组成 内容区 内边距 边框 border-width border-color border-style border 外边距 负值 auto 简写属性 垂直外边距的重叠 浏览器默认设置 内联元素的盒子 简介 在网页中&#xff0c;一切都是可以看作为“盒子”。 在css处理网页的时候&…

音游判定原理详解——从触摸屏幕到判定音符【Project SEKAI攻略】

“音乐游戏”一般简称为“音游”&#xff0c;玩家需要配合音乐的节奏来进行一定的动作。 《Project SEKAI》作为一个“移动端音游”&#xff0c;绝大多数玩家会使用手机、平板电脑等移动设备的触摸屏进行游玩&#xff0c;也有极少数的玩家不按常理出牌&#xff0c;使用手台、键…

英国站亚马逊纽扣电池标准

英国标准协会&#xff08;BSI&#xff09;于2021年4月30日发布了纽扣&#xff08;非锂&#xff09;和纽扣&#xff08;锂&#xff09;电池的国家标准PAS 7055:2021。 该标准是根据2005年通用产品安全法规的规定制定的(GPSR) 并关注投放到英国市场的产品的安全性。 PAS 7055:202…

数据库实验 | 第1关:建立和调用存储过程(不带输出参数的存储过程)

任务描述 本关任务&#xff1a; 该实验是针对数据表jdxx&#xff0c;该数据表有四个字段&#xff0c;分别是省份(sf)、城市(cs)、区县(qxmc)、街道(name)。 例如&#xff0c;查询天心区(qxmc)的所有字段的值结果如图所示 任务要求 建立存储过程 dqxx(in city varchar(10),i…

6.S081——虚拟内存部分——xv6源码完全解析系列(4)

0.briefly speaking 点击跳转到上一篇博客 好&#xff0c;现在进入下一个话题&#xff0c;就是物理内存分配器(kernel/kalloc.c)。在简单介绍完内核态的物理内存分配器之后&#xff0c;之后简单带过一下两个头文件riscv.h和memorylayout.h这两个头文件&#xff0c;因为它们都…

.Net Core从零学习搭建权限管理系统 - 课程简介

课程简介目录 &#x1f680;前言一、课程背景二、课程目的三、系统功能四、系统技术架构五、课程特点六、课程适合人员七、课程规划的章节八、最后 &#x1f680;前言 本文是《.Net Core从零学习搭建权限管理系统》教程专栏的导航站&#xff08;点击链接&#xff0c;跳转到专栏…

(1条消息) CodeForces 1278 B.A and B(Math)

题目如下&#xff1a; 题解 or 思路 首先我们需要知道&#xff1a; 对于&#xff1a; s u m 1 2 3 4 . . . n sum 1 2 3 4 ... n sum1234...n s u m a b , ( a ∈ [ 0 , s u m ] ) sum a b, (a \in [0, sum]) sumab,(a∈[0,sum]) 这个在此就不再证明 于是我…

vcpkg添加自定义包安装

文章目录 前言新建overlay-ports编写baseline.json编写openssl.json编写配置修改vcpkg.json修改portfile.cmake 挂载安装后话 前言 vcpkg收集了很多C的包&#xff0c;可总是会有没收录进去的&#xff0c;以openssl 3.0.0版本举例&#xff0c;这个版本vcpkg没有收录进去&#x…

String的不可变特性

1 问题 如何理解“String是不可变的&#xff0c;但是可以变”&#xff1f; 2 方法 &#xff08;1&#xff09;String的不可变特性体现在内容和长度 首先在idea中点开查看String这个类是如何定义的 可以看到这样一行代码&#xff1a;private final char value[]; 正是因为这个数…

基于Simulink单载波链路射频波束成形仿真

一、前言 此示例展示了如何在 Simulink中对 IEEE 802.11ad单载波链路进行建模&#xff0c;其中包括具有射频波束成形功能的相控阵天线。 二、介绍 此模型模拟具有射频波束成形的 802.11ad 单载波 &#xff08;SC&#xff09;链路。多个数据包通过自由空间传输&#xff0c;然后射…

图片转为pdf怎么弄?简单几个步骤轻松转换

在日常工作和生活中&#xff0c;我们常常需要将图片转换为PDF格式的文档&#xff0c;以满足资料存档和共享的需要。虽然转换过程看起来有些麻烦&#xff0c;但只要选择正确的工具和方法&#xff0c;就能轻松完成。 下面&#xff0c;小编将为大家介绍两种常见的将图片转换为PDF…

生成对抗网络(GAN) 理论概念、改进模型与练习题

生成对抗网络&#xff08;GAN&#xff09; 生成对抗网络的基本概念模型提出模型类型模型功能模型目标模型结构模型训练模型实质模型缺点模型生成器的构造模型损失函数 生成对抗网络的改进模型DCGANWGANWGAN-GPACGAN 生成对抗网络的题型 生成对抗网络的基本概念 模型提出 2014…

Grad-CAM的详细介绍和Pytorch代码实现

Grad-CAM (Gradient-weighted Class Activation Mapping) 是一种可视化深度神经网络中哪些部分对于预测结果贡献最大的技术。它能够定位到特定的图像区域&#xff0c;从而使得神经网络的决策过程更加可解释和可视化。 Grad-CAM 的基本思想是&#xff0c;在神经网络中&#xff…

体验编写Vue框架项目实例的详细步骤2(包括git仓库使用,element-ui的使用和eslint校验关闭)

1.在src目录下新建pages文件夹用来放页面。新建文件Index.vue&#xff0c;首页 在Index.vue中搭建vue基本结构。 在element官网Element - The worlds most popular Vue UI framework中选择想要的组件。 我选择是Container布局容器。选择好样式点击显示代码复制相关代码至Ind…

【安全运维】小微企业的安全运维工具用哪款好?

即使是小微企业&#xff0c;也同样面临着安全运维的困扰&#xff0c;同样面临着数据泄露、资产难管理的问题&#xff0c;因此选择一款合适的安全运维工具是非常必要的。那你知道小微企业的安全运维工具用哪款好&#xff1f; 小微企业的安全运维工具用哪款好&#xff1f; 【回…

全景视角下的世界探索——三维全景地图

引言&#xff1a;随着数字技术和虚拟现实技术的发展&#xff0c;三维全景地图已成为一种新型地图展示方式&#xff0c;深受人们的关注和喜爱。三维全景地图以其真实逼真、互动性强、展示效果好等特点&#xff0c;正在越来越多的领域得到应用。 三维全景地图的特点 1.真实逼真 …

Elasticsearch(黑马)

初识elasticsearch ​​. 安装elasticsearch 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net 1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的…

【云原生概念和技术】1.2 云原生技术概括(下)

如果想了解或者学习云原生的友友们&#xff0c;欢迎订阅哦&#xff5e;&#x1f917;&#xff0c;目前一周三更&#xff0c;努力码字中&#x1f9d1;‍&#x1f4bb;…目前第一章是一些介绍和概念性的知识&#xff0c;可以先在脑海里有一个知识的轮廓&#xff0c;从第二章开始就…

Talk预告 | ICLR‘23 北京大学楼家宁:针对鲁棒聚类问题的接近最优核心集

本期为TechBeat人工智能社区第485期线上Talk&#xff01; 北京时间3月29日(周三)20:00&#xff0c;北京大学信息科学技术学院——楼家宁的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “针对鲁棒聚类问题的接近最优核心集”&#xff0c;届时将针…

nodejs+vue在线课程管理系统

随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本在线课程管理系统有管理员&#xff0c;教师&#xff0c;学生。管理员功能有个人中心&#xff0c;学生管理&#xff0c;教师管理&#xff0c;在线课程管理&#xff0c;课件信息管理&#x…