装饰模式(大话设计模式)C/C++版本

装饰模式

在这里插入图片描述

需求分析:

1. 选择服饰 => 服饰类
2. 输出结果
对象是人 => 人类

将Person类中一大堆服饰功能抽象出服饰类,然后通过Person类聚合服饰属性,通过Set行为来设置服饰属性,最后达到灵活打扮的效果

装饰模式
动态地给一个对象添加一些额外的职责,就增加功能来说 装饰模式比生成子类更为灵活
1. 装饰对象的实现和如何使用该对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。
2. 装饰模式是结构性的模式,将所需要的功能按正确的顺序串联起来进行控制

使用场景

之前:旧类新增功能,向旧类添加新的属性和新的行为,增加了类的复杂度,破坏了开闭原则;
现在:装饰功能作为一个单独类存在,就可以在运行时灵活的增加到旧类中。

总结:
将类中的装饰功能从类中移除(简化类,避免类的膨胀),具体装饰类通过聚合父类来灵活增加父类功能;
有效的将一个大类的核心职责和装饰功能区分开了。

C++

#include <iostream>
using namespace std;

// ConcreteComponent即Component
class Person
{
protected:
    string name;

public:
    Person(){};
    Person(string name) : name(name){};
    virtual void show()
    {
        cout << "装扮的" << name << endl;
    }
};

// Decorator类(装饰类),继承了Persson类,并且弱拥有Person类
class Finery : public Person
{
protected:
    Person *component;

public:
    Finery() : component(nullptr) {}
    void Decorate(Person *component)
    {
        this->component = component;
    }
    virtual void show()
    {
        if (component)
            component->show();
    }
};

// ConcreteDecorator类
class TShirts : public Finery
{
public:
    virtual ~TShirts() {}
    virtual void show()
    {
        cout << "Tshirt" << endl;
        Finery::show();
    }
};

// ConcreteDecorator类
class Jeans : public Finery
{
public:
    virtual ~Jeans() {}
    virtual void show()
    {
        cout << "Jeans" << endl;
        Finery::show();
    }
};

int main()
{
    Person *p = new Person("小菜");
    TShirts *oTShirt = new TShirts();
    Jeans *oJeans = new Jeans();
    oTShirt->Decorate(p);
    oJeans->Decorate(oTShirt);
    oJeans->show();

    delete p;
    p = nullptr;
    delete oTShirt;
    oTShirt = nullptr;
    delete oJeans;
    oJeans = nullptr;
    return 0;
}

C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Component 类型定义
typedef struct Person
{
    char *name;
    void (*show)(struct Person *);
} Person;

// Decorator 类型定义
typedef struct Finery
{
    Person base;
    Person *component;
} Finery;

// ConcreteDecorator 类型定义
typedef struct TShirts
{
    Finery base;
} TShirts;

typedef struct Jeans
{
    Finery base;
} Jeans;

// 实现 Finery 的 show 方法
void finery_show(Finery *self)
{
    if (self->component && self->component->show)
    {
        self->component->show(self->component);
    }
}

// 实现 TShirts 的 show 方法
void tshirts_show(TShirts *self)
{
    printf("Tshirt\n");
    finery_show((Finery *)self);
}

// 实现 Jeans 的 show 方法
void jeans_show(Jeans *self)
{
    printf("Jeans\n");
    finery_show((Finery *)self);
}

// Finery 构造函数
Finery *finery_new(Person *component)
{
    Finery *self = malloc(sizeof(Finery));
    self->base.show = finery_show;
    self->component = component;
    return self;
}

// TShirts 构造函数
TShirts *tshirts_new(Finery *component)
{
    TShirts *self = malloc(sizeof(TShirts));
    self->base.base.show = tshirts_show;
    self->base.component = component;
    return self;
}

// Jeans 构造函数
Jeans *jeans_new(Finery *component)
{
    Jeans *self = malloc(sizeof(Jeans));
    self->base.base.show = jeans_show;
    self->base.component = component;
    return self;
}

// ConcreteComponent 方法实现
void person_show(Person *self)
{
    printf("装扮的 %s\n", self->name);
}

int main()
{
    Person *p = malloc(sizeof(Person));
    p->name = strdup("小菜");
    p->show = person_show;

    Finery *oTShirt = finery_new(p);
    TShirts *tshirts = tshirts_new(oTShirt);

    Finery *oJeans = finery_new(tshirts);
    Jeans *jeans = jeans_new(oJeans);

    jeans->base.base.show(jeans);

    free(p->name);
    free(p);
    free(tshirts);
    free(oTShirt);
    free(jeans);
    free(oJeans);
    return 0;
}

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

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

相关文章

【Java--数据结构】栈:不仅仅是数据存储,它是编程的艺术

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 栈 栈的方法介绍 入栈push 出栈pop和 瞄一眼peek 判空isEmpty和判满isFull 模拟实现栈 push入栈 pop出栈和peek 测试 使用泛型实现栈 测试 使用链表实现栈&#xff08…

【leetcode】整数反转

给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 1&#xff1a; …

运动控制问题

第一类运动控制问题是指被控制对象的空间位置或轨迹运动发生改变的运动控制系统的控制问题。这类运动控制问题在理论上完全遵循牛顿力学定律和运动学原则。 1、运动控制问题 第1类运动控制的核心是研究被控对象的运动轨迹 、分析运动路径、运动速度、加速度与时间的关系,常用…

【香菇带你学Linux】Linux环境下gcc编译安装【建议收藏】

文章目录 0. 前言1. 安装前准备工作1.1 创建weihu用户1.2 安装依赖包1.2.1 安装 GMP1.2.2 安装MPFR1.2.3 安装MPC 2. gcc10.0.1版本安装3. 报错解决3. 1. wget下载报错 4. 参考文档 0. 前言 gcc&#xff08;GNU Compiler Collection&#xff09;是GNU项目的一部分&#xff0c;…

TensorBoard ,PIL 和 OpenCV 在深度学习中的应用

重要工具介绍 TensorBoard&#xff1a; 是一个TensorFlow提供的强大工具&#xff0c;用于可视化和理解深度学习模型的训练过程和结果。下面我将介绍TensorBoard的相关知识和使用方法。 TensorBoard 简介 TensorBoard是TensorFlow提供的一个可视化工具&#xff0c;用于&#x…

JVM:垃圾回收器

文章目录 一、介绍二、年轻代-Serial垃圾回收器三、老年代-SerialOld垃圾回收器四、年轻代-ParNew垃圾回收器五、老年代-CMS&#xff08;Concurrent Mark Sweep&#xff09;垃圾回收器六、年轻代-Parllel Scavenge垃圾回收器七、Parallel Old垃圾回收器八、G1垃圾回收器 一、介…

Python实战MySQL:数据库操作全流程详解

更多Python学习内容&#xff1a;ipengtao.com MySQL是一种广泛使用的关系型数据库管理系统&#xff0c;Python可以通过多种方式与MySQL进行交互。本文将详细介绍如何使用Python操作MySQL数据库&#xff0c;包括安装必要的库、连接数据库、执行基本的CRUD&#xff08;创建、读取…

JAVA String类最全分析

一、介绍 StringSerializable实现它&#xff0c;String可以串行化&#xff0c;可以在网络上传输ComparableString对象可以相互比较CharSequenceObject String class Main{public static void main(String[] args) {//1.String 对象用于保存字符串&#xff0c;也就是一组字符…

Android ImageDecoder把瘦高/扁平大图相当于fitCenter模式decode成目标小尺寸Bitmap,Kotlin

Android ImageDecoder把瘦高/扁平大图相当于fitCenter模式decode成目标小尺寸Bitmap&#xff0c;Kotlin val sz Size(MainActivity.SIZE, MainActivity.SIZE)val src ImageDecoder.createSource(mContext?.contentResolver!!, uri)val bitmap ImageDecoder.decodeBitmap(sr…

MySQL更新和删除(DML)

DML-修改数据 UPDATE 表名 SET 字段1 值1&#xff0c;字段2值2&#xff0c;....[WHERE 条件] 例如 1.这个就是把employee表中的这个name字段里面并且id字段为1的名字改为itheima update employee set nameitheima where id 1; 2.这个就是把employee这个表中的name字段和…

SpringMVC源码分析

文章目录 概要启动阶段请求阶段 概要 以下是调试mvc源码过程中用到的demo以及配置文件 webapp/WEB-INF/web.xml <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://…

熊海CMS漏洞练习平台的一次xss、sql注入、越权黑盒思路分析

简介 熊海CMS是由熊海开发的一款功能丰富的网站综合管理系统&#xff0c;广泛应用于个人博客、个人网站以及企业网站&#xff0c;本文章用于黑盒测试&#xff0c;如果需要「源码审计」后台回复【「CMS」】获取即可&#xff0c;精心准备了40多个cms源码漏洞平台&#xff0c;供宝…

记一次docker容器安装MySQL,navicat无法连接报错(10060错误)

今天在云服务器上使用docker部署mysql 8.0.11时&#xff0c;遇到了一个诡异的问题&#xff0c;在云服务器的docker容器内可以连接上mysql&#xff0c;然而在自己电脑上连接mysql时报错&#xff1a;Can‘t connect to MySQL server on localhost (10060) 下面是网上搜寻的几种可…

《SpringBoot 整合 Prometheus 采集自定义指标》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

C语言 ——— const关键字

目录 const修饰变量 const修饰指针变量 const放在指针类型之前 const放在指针类型之后 小结 const修饰变量 当 const 修饰 int类型 的 变量a 后&#xff0c;此时的 变量a 就具有长属性&#xff0c;就不能被赋值为其他的值 将 变量a的地址 存储到 指针变量pa 中&#xff…

计算机网络——常见问题汇总

1. introduction 1.1 Explain what a communication protocol is and why its important. A communication protocol is a set of rules and conventions(公约) that govern(统治) how data is transmitted and received between devices(设备), systems, or entities in a ne…

1、BOREDHACKERBLOG:社交网络

靶机&#xff1a;https://www.vulnhub.com/entry/boredhackerblog-social-network,454/ 参考&#xff1a;Vulnhub靶机&#xff1a;BOREDHACKERBLOG: SOCIAL NETWORK_boredhackerblog系列-CSDN博客 需要使用virtualbox。 先去官网下载了最新版的vietualbox&#xff0c;以及把这…

使用 Unstructured.io 和 Elasticsearch 向量数据库搜索复杂文档

作者&#xff1a;来自 Elastic Amy Ghate, Rishikesh Radhakrishnan, Hemant Malik 使用非结构化和 Elasticsearch 向量数据库为 RAG 应用程序提取和搜索复杂的专有文档 在使信息可搜索之前解析文档是构建实际 RAG 应用程序的重要步骤。Unstructured.io 和 Elasticsearch 在此…

Admin.NET源码学习(2:安装并运行前端)

根据Admin.NET的GitHub主页介绍&#xff0c;前端运行步骤需要运行pnpm命令。百度pnpm的话&#xff0c;需要支持npm相关的命令支持。   根据参考文献4&#xff0c;安装Node.js后会提供npm命令支持&#xff08;npm是Node.js的软件包管理器&#xff0c;用于安装、发布和共享Jav…

FreeRTOS 入门 知识

什么是FreeRTOS FreeRTOS 是一个轻量级的实时操作系统&#xff08;RTOS&#xff09;&#xff0c;由 Richard Barry 在 2003 年开发&#xff0c;并且由亚马逊的 FreeRTOS 项目&#xff08;一个由 Amazon Web Services (AWS) 支持的开源项目&#xff09;进一步推动和发展。FreeR…