设计模式之装饰模式

一、概念

装饰模式是一种结构型设计模式,允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。

二、构造

部件(Component)声明封装器和被封装对象的公用接口。

具体部件(Concrete Component)类是被封装对象所属的类。它定义了基础行为,但装饰类可以改变这些行为。

基础装饰(Base Decorator)类拥有一个指向被封装对象的引用成员变量。该变量的类型应当被声明为通用部件接口,这样它就可以引用具体的部件和装饰。装饰基类会将所有操作委派给被封装的对象。

具体装饰类(Concrete Decorators)定义了可动态添加到部件的额外行为。具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为。

客户端(Client)可以使用多层装饰来封装部件,只要它能使用通用接口与所有对象互动即可。

三、应用场景

class Component {
public:
    virtual ~Component() {}
    virtual std::string Operation() const = 0;
};

class ConcreteComponent : public Component {
public:
    std::string Operation() const override {
        return "ConcreteComponent";
    }
};

class Decorator : public Component {
protected:
    Component* component_;

public:
    Decorator(Component* component) : component_(component) {
    }
    std::string Operation() const override {
        return this->component_->Operation();
    }
};

class ConcreteDecoratorA : public Decorator {
public:
    ConcreteDecoratorA(Component* component) : Decorator(component) {
    }
    std::string Operation() const override {
        return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
    }
};

class ConcreteDecoratorB : public Decorator {
public:
    ConcreteDecoratorB(Component* component) : Decorator(component) {
    }

    std::string Operation() const override {
        return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
    }
};

int main() {
    Component* simple = new ConcreteComponent;
    std::cout << "Client: I've got a simple component:\n";
    std::cout << "RESULT: " << simple->Operation();
    std::cout << "\n\n";

    Component* decorator1 = new ConcreteDecoratorA(simple);
    Component* decorator2 = new ConcreteDecoratorB(decorator1);
    std::cout << "Client: Now I've got a decorated component:\n";
    std::cout << "RESULT: " << decorator2->Operation();
    std::cout << "\n";

    delete simple;
    delete decorator1;
    delete decorator2;

    return 0;
}

装饰模式总结

优点:

  • 无需创建新子类即可扩展对象的行为。
  • 可以在运行时添加或删除对象的功能。
  • 可以用多个装饰封装对象来组合几种行为。
  • 单一职责原则。可以将实现了许多不同行为的一个大类拆分为多个较小的类。

缺点:

  • 在封装器栈中删除特定封装器比较困难。
  • 实现行为不受装饰栈顺序影响的装饰比较困难。
  • 各层的初始化配置代码看上去可能会很糟糕。

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

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

相关文章

路由器基础(五): OSPF原理与配置

开放式最短路径优先 (Open Shortest Path First,OSPF) 是一个内部网关协议 (Interior Gateway Protocol,IGP),用于在单一自治系统(Autonomous System,AS) 内决策路由。OSPF 适合小型、中型、较大规模网络。OSPF 采用Dijkstra的最短路径优先算法 (Shortest Pat…

腾讯云24元香港服务器有用过的吗?性能如何?

香港云服务器可以选择腾讯云香港地域的轻量应用服务器&#xff0c;轻量2核2G配置、20M峰值带宽、40G SSD系统盘&#xff0c;优惠价格24元一个月&#xff0c;Linux系统是288元一年&#xff0c;Windows系统是360元一年&#xff0c;腾讯云百科txybk.com分享腾讯云香港轻量应用服务…

php去除字符串两边空格空字符串换行方法

在PHP中&#xff0c;可以使用以下几种方法去除字符串两边的空格、空字符串和换行符&#xff1a; 使用trim()函数去除字符串两边的空格和空字符串&#xff0c;例如&#xff1a; $str " Hello World! "; $trimmed trim($str); echo $trimmed; 使用preg_replace(…

代码随想录打卡第62天|● 503.下一个更大元素II ● 42. 接雨水

● 503.下一个更大元素II 题目&#xff1a;给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第…

C语言打印出九九乘法表

#include<stdio.h> int main() {int i,j;for(i1;i<9;i){for(j1;j<9;j){printf("%d*%d%d\t",i,j,i*j); //\t制表符}printf("\n"); //\n输出个回车} }

解决Lightroom Classic无法使用修改照片的问题

Lightroom Classic是一款广泛使用的照片编辑软件&#xff0c;但在使用过程中&#xff0c;可能会遇到无法修改照片的问题。修改照片这个模块无法使用&#xff0c;功能按钮呈现灰色&#xff0c;无法点击。本文将介绍几种常见的解决方法&#xff0c;帮助您快速解决Lightroom无法使…

【C语言】函数的系统化精讲(一)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 &#x1f308;作者寄语 &#x1f308;&#xff1a; 小菜鸟的力量不在于它的体型&#xff0c;而在于它内心的勇气和无限的潜能&#xff0c;只要你有决心&#xff0c;就没有什么事情是不可能的…

Redis-使用java代码操作Redis->java连接上redis,java操作redis的常见类型数据存储,redis中的项目应用

java连接上redisjava操作redis的常见类型数据存储redis中的项目应用 1.java连接上redis package com.zlj.ssm.redis;import redis.clients.jedis.Jedis;/*** author zlj* create 2023-11-03 19:27*/ public class Demo1 {public static void main(String[] args) { // …

2022年电工杯数学建模B题5G网络环境下应急物资配送问题求解全过程论文及程序

2022年电工杯数学建模 B题 5G网络环境下应急物资配送问题 原题再现&#xff1a; 一些重特大突发事件往往会造成道路阻断、损坏、封闭等意想不到的情况&#xff0c;对人们的日常生活会造成一定的影响。为了保证人们的正常生活&#xff0c;将应急物资及时准确地配送到位尤为重要…

chromedp库编写程序

步骤1&#xff1a;首先&#xff0c;我们需要导入chromedp库&#xff0c;以便使用它来下载网页内容。 import chromedp 步骤2&#xff1a;然后&#xff0c;我们需要创建一个函数&#xff0c;该函数接受一个URL作为参数&#xff0c;并使用chromedp库下载该URL的内容。 func do…

pytorch复现_conv2d

import numpy as npdef conv2d(inputs, kernels, bias, stride, padding):"""正向卷积操作inputs: 输入数据&#xff0c;形状为 (C, H, W)kernels: 卷积核&#xff0c;形状为 (F, C, HH, WW)&#xff0c;C是图片输入层数&#xff0c;F是图片输出层数bias: 偏置&…

Synchronized与锁升级

一&#xff1a;java对象内存布局 对象在堆内存的存储布局可以划分为三个部分&#xff1a;对象头&#xff08;Header&#xff09;、实例数据&#xff08;Instance Data&#xff09; 和对齐填充 二&#xff1a;对象在堆内存中的存储布局 1&#xff1a;对象头 &#xff08;在64…

睿思BI已支持3D图形

从睿思BI旗舰版V5.3开始&#xff0c;系统支持如下3D图形&#xff1a; 3D地球 3D地图 飞线图 3D金字塔 睿思BI采用ThreeJS实现3D功能&#xff0c;用户也可以基于系统接口&#xff0c;采用ThreeJS在数据大屏中实现自己的3D图形。 系统演示地址&#xff1a;睿思BI旗舰版https://…

C#,数值计算——偏微分方程,Mglin的计算方法与源程序

1 文本格式 using System; using System.Collections.Generic; namespace Legalsoft.Truffer { public class Mglin { private int n { get; set; } private int ng { get; set; } private double[,] uj1 { get; set; } private Lis…

【原创】java+swing+mysql校园共享单车管理系统设计与实现

摘要&#xff1a; 校园共享单车作为一种绿色、便捷的出行方式&#xff0c;在校园内得到了广泛的应用。然而&#xff0c;随着单车数量的增加&#xff0c;管理难度也不断加大。如何提高单车的利用率和管理效率&#xff0c;成为校园共享单车发展面临的重要问题。本文针对这一问题…

苹果手机微信照片过期怎么恢复?分享3个实用技巧!

很多时候&#xff0c;我们会在微信中给家人和朋友分享一些有趣的照片。但有时会因为各种原因&#xff0c;比如还没有来得及查看或保存&#xff0c;从而导致这些照片过期失效。 如果这些图片我们还需要用到&#xff0c;那么将它们找回来是很有必要的事情。微信照片过期怎么恢复…

LeetCode.6 N字形变换

一开始想的是真的创建一个数组 去按照题目所给的要求填入数据 最后输出不为空的数组项 但是不仅时间复杂度高 而且错误频繁出现 最终也没有提交成功 查阅题解后发现数组并不重要 假设我们忽略掉数组中的那些空白项 最终输出的结果就是numRows行的字符串的拼接 string conver…

记一次pdjs时安装glob出现,npm ERR! code ETARGET和npm ERR! code ELIFECYCLE

如往常一样&#xff0c;我使用pdjs来编译proto文件&#xff0c;但出现了以下报错&#xff1a; 大致就是pdjs的util在尝试执行npm install glob^7.2.1 escodegen^1.13.0时出错了 尝试手动执行安装&#xff0c;escodegen被正确安装&#xff0c;但glob^7.2.1出错 npm ERR! code E…

一个JS版寻路的实现

js版的寻路的测试 20231104_161146 path get_v8: function (x_inc, y_inc) {if (x_inc 0) {if (y_inc < 0) {return [[0, -1], [-1, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [1, 1], [0, 1]];} else if (y_inc > 0) {return [[0, 1], [-1, 1], [1, 1], [-1, 0], [1, 0…