设计模式之组合设计模式

news2024/9/19 13:04:48

一、组合设计模式概念

组合模式 (Component) 是一种结构型设计模式,将对象组合成树形结构以表示“部分-整体”的层次结构。

组合模式使得用户对单个对象和组合对象的使用具有唯一性

 适用场景

  • 想要表示对象的部分-整体层次结构。
  • 想要客户端忽略组合对象与单个对象的差异,客户端将统一地使用组合结构中的所有对象。

组合设计模式的结构

  1. 组件 (Component) 接口描述了树中简单项目和复杂项目所共有的操作。
  2. 叶节点 (Leaf) 是树的基本结构, 它不包含子项目。一般情况下, 叶节点最终会完成大部分的实际工作, 因为它们无法将工作指派给其他部分。
  3. 容器 (Container)——又名 “组合 (Composite)”——是包含叶节点或其他容器等子项目的单位。 容器不知道其子项目所属的具体类, 它只通过通用的组件接口与其子项目交互。容器接收到请求后会将工作分配给自己的子项目, 处理中间结果, 然后将最终结果返回给客户端。
  4. 客户端 (Client) 通过组件接口与所有项目交互。 因此, 客户端能以相同方式与树状结构中的简单或复杂项目交互。

代码如下:

问题:复杂订单的计算,有两类对象:产品和盒子。一个盒子中可以包含多个产品或者多个小盒子这些盒子中可以再包含产品或者小盒子,以此类推。


解决方案:将对象组成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性。

#include <iostream>
#include <list>
#include <string>
//接口:不管是商品还是盒子,都依赖这个接口//为了实现树形结构
class OrderNode
{
protected:
	OrderNode* m_parent;
	float m_price;
public:
	virtual ~OrderNode() {}
	OrderNode() : m_parent(nullptr), m_price(0.0f) {}
	OrderNode(OrderNode* parent, float price) : m_parent(nullptr), m_price(price) {}

	void setParent(OrderNode* parent) { m_parent = parent; }
	OrderNode* getParent() { return m_parent; }
	virtual bool isComposite() { return false; }

	void setPrice(float price) { m_price = price; }
    float getPrice() { return m_price; }
    virtual std::string Operation() = 0;
};

class Product : public OrderNode
{
public:
	~Product() {}
    Product(float price):OrderNode(nullptr,price) {}
    std::string Operation() override{ return "Product"; }
};

class Box : public OrderNode
{
protected:
    std::list<OrderNode*> m_children;
public:
	~Box() {}
	Box() {}
    Box(OrderNode* parent,float price):OrderNode(parent, price) {}
	bool isComposite() override { return true; }
	void Add(OrderNode* node) 
	{
		m_children.push_back(node);
		node->setParent(this); 
		m_price += node->getPrice();
	}
	void Remove(OrderNode* node)
	{
        m_children.remove(node);//只是在容器中移除
        node->setParent(nullptr);
        m_price -= node->getPrice();

	}
   virtual std::string Operation() override
   { 
	   std::string result;
	   m_price = 0.0f;//重要
	   for (auto c : m_children)
	   {
		   if (c == m_children.back())
		   {
               result += c->Operation();
		   }
		   else
		   {
               result += c->Operation() + ",";
		   }
		   m_price += c->getPrice();
	   }
	   return "Box(" + result + ")";
   }
};

void clientCode(OrderNode* node)
{
	std::cout << "结构:" << node->Operation() << std::endl;
    std::cout << "价格:" << node->getPrice() << std::endl;
}
int main()
{
    /*Box* box1 = new Box(nullptr, 0.0f);
    Box* box2 = new Box(nullptr, 0.0f);
    Product* product1 = new Product(nullptr, 10.0f);
    Product* product2 = new Product(nullptr, 20.0f);
    Product* product3 = new Product(nullptr, 30.0f);
    Product* product4 = new Product(nullptr, 40.0f);
    box1->Add(product1);
    box1->Add(product2);
    box2->Add(product3);
    box2->Add(product4);
    box1->Add(box2);
    clientCode(box1);
    delete box1;
    delete box2;
    delete product1;
    delete product2;
    delete product3;
    delete product4;*/

	std::cout << "处理叶子节点:" << std::endl;
	Product leaf( 5.0f);
	clientCode(&leaf);

	std::cout << std::endl;
	std::cout << "处理组合节点:" << std::endl;
	Box tree;
	Box branch1;
    Box branch2;
	Product leaf_1(5.0f);
    Product leaf_2(10.0f);
    Product leaf_3(15.0f);
	tree.Add(&branch1);
    tree.Add(&branch2);
    branch1.Add(&leaf_1);
    branch1.Add(&leaf_2);
    branch2.Add(&leaf_3);
    clientCode(&tree);

    std::cout << std::endl;
	tree.Add(&leaf);
	clientCode(&tree);
    return 0;
}

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

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

相关文章

基于扣子(Coze)打造第一个智能体——个性化对话机器人

文章目录 一&#xff0c;智能体体验二&#xff0c;动手打造一个自己的智能体1&#xff0c;主页点击创建机器人1.1 创建一个新的机器人1.2 修订Bot基础信息1.3 工具编排信息修订人设和回复逻辑、增补开场白等 2&#xff0c;使用插件优化机器人3&#xff0c;使用工作流优化机器人…

2024/9/14 408大题专项训练之存储系统

组相联映射怎么算组号&#xff1f; 有cache总大小/路数xcache大小 物理地址与虚拟地址位数不一定相等&#xff0c;但是她们页内地址和块内地址位数是一样的&#xff01;

栈OJ题——用栈实现队列

文章目录 一、题目链接二、解题思路三、解题代码 一、题目链接 用栈实现队列 二、解题思路 三、解题代码 class MyQueue {public Stack<Integer> stack1 ;public Stack<Integer> stack2;public MyQueue() {stack1 new Stack<>();stack2 new Stack<&g…

C++中类的定义

一、类的定义格式 1、首先我们创建一个类&#xff1a; #include<iostream> using namespace std;class Stack {//公有的 public://定义一个成员函数并给一个默认的缺省值void Init(int n 6){int* arr (int*)malloc(sizeof(int) * n);if (arr NULL){perror("mal…

ruby和python哪个好学

Ruby和python都挺好学的。建议学习Python&#xff0c;语法的话&#xff0c;Python相对更简洁。而且Python应用场合更广泛&#xff0c;运维、网站开发、数据处理、科学研究都可以。 Ruby和Python十分相似&#xff0c;有很多共同点&#xff0c;但也有一些不同之外&#xff0c;以…

视频提取文案,这5种方法让你轻松提取出来

视频文案的提取成为了许多创作者和营销人员的日常需求。无论是从短视频中提取精彩台词&#xff0c;还是将教育视频转化为学习资料&#xff0c;掌握高效的视频文案提取方法都显得尤为重要。今天&#xff0c;就来给大家分享5种视频文案提取方法&#xff0c;快来一起看看吧。 方法…

App及web反编译方案

APP反编译代码的工具下载&#xff1a; 下载地址&#xff1a;APK逆向三件套apktool-2.9.3.jar&#xff0c;dex2jar-2.0.zip&#xff0c;jd-gui-windows-1.6.6资源-CSDN文库 》dex2jar: 把dex文件转成jar文件 》 jd-gui: 这个工具用于将jar文件转换成java代码 》APKTool: 首先把…

【HCIA-Datacom】IPv4地址介绍

| | &#x1f449;个人主页&#xff1a;Reuuse 希望各位多多支持&#xff01;❀ | &#x1f449;HCIA专栏博客 | 最后如果对你们有帮助的话希望有一个大大的赞&#xff01; | ⭐你们的支持是我最大的动力&#xff01;⭐ | 目录 IPv4地址定义IPv4地址分类方式二级目录三级目录 I…

研1日记12

1. 改19->10 2. 学习数据不平衡问题 1. 欠采样 合并两个样本数据 两种方式 1. 按原分布比例划分。sklearn中train_test_split里&#xff0c;参数stratify含义解析_traintestsplit参数stratify-CSDN博客 3.刘二大人 卷积操作 待看论文&#xff1a; 刘老师指导&#xff1a…

PRD 在产品中的重要作用与撰写技巧(文末附PRD模板下载)

对于产品经理而言&#xff0c;PRD&#xff08;Product Requirement Document&#xff0c;产品需求文档&#xff09;是将产品概念转化为实际产品的关键桥梁。以下是关于如何写好 PRD 的详细指南&#xff1a; 一、PRD 的主要作用 统一团队认知 PRD 是产品团队的 “通用语言”。…

掌握 Spring:从新手到高手的常见问题汇总

一提起Spring&#xff0c;总感觉有太多知识&#xff0c;无法详尽&#xff0c;有些基础理解就先不说了&#xff0c;相信大家都已经用过Spring了 下面简单针对常见Spring面试题做些回答 核心特性 IOC容器spring事件资源管理国际化校验数据绑定类型转换spirng表达式面向切面编程……

视频监控基础学习

IPC&#xff1a;网络摄像机 NVR&#xff1a;网络硬盘录像机产品&#xff0c;搭配IPC使用。集成存储、解码显示、拼接控制、智能分析等多种功能于一体。一机多用&#xff0c;部署简单&#xff0c;功能齐全。安全可靠&#xff0c;适用于各类场景。 ONVIF协议&#xff1a;网络摄像…

数据集 wider_face 人脸数据集 人脸检测 >> DataBall

数据集 wider 人脸检测数据集 WIDER FACE: A Face Detection Benchmark inproceedings{yang2016wider, Author {Yang, Shuo and Luo, Ping and Loy, Chen Change and Tang, Xiaoou}, Booktitle {IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, Title…

巴西电商市场规模、前景及支付方式(pix、Boleto)

一、巴西电商市场分析 作为拉丁美洲最大经济体&#xff0c;巴西在拉丁美洲经济中占据领先地位&#xff0c;根据巴西地理与统计研究所(IBGE)的数据&#xff0c;2023年巴西GDP达到2.2万亿美元&#xff0c;跃居世界第九大经济体。数字化进程以及经济多元化推进正在推动该国中产阶…

基于SpringBoot+Vue的高校教材订购管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

jmeter吞吐量控制器

一、吞吐量控制器作用&#xff1a;旨在混合场景中&#xff0c;控制样本数&#xff0c;通常在比例场景中使用 吞吐量控制器提供了两种控制模式&#xff1a; 百分比执行&#xff08;Percent Executions&#xff09;&#xff1a; 吞吐量控制器会根据配置的百分比来决定其下的作用…

快速完成论文初稿写作的ChatGPT提示词分享

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 随着人工智能技术的迅速发展&#xff0c;ChatGPT已经成为学术写作中不可忽视的工具。它不仅能帮助研究者提高写作效率&#xff0c;还能在初稿撰写过程中提供结构化的建议和内容生成支持…

xshell密钥方式连接阿里云Linux

前提条件 有阿里云ECS linux实例安装好xshell工具 步骤 创建密钥对并绑定ECS实例 浏览器登录阿里云-->控制台-->ECS服务器-->网络与安全-->密钥对-->创建密钥对 根据提示填写密钥名称-->选中默认资源组-->创建 创建完成&#xff0c;会自动下载密钥对的…

看Threejs好玩示例,学习创新与技术(二)

本文接上篇内容&#xff0c;继续挖掘应用ThreeJS的一些创新算法。 本文理解难度比较大&#xff0c;可以先看一些概念&#xff0c;在难的地方培养一些意识即可。 1、扭曲的自然 下面图本身是矩形的&#xff0c;为何它可以这么扭曲呢&#xff1f;它在随机处带有一定的规律&…

多米优选APP源码系统开发

多米优选是一种基于卷轴模式的电商平台系统&#xff0c;它通过滚动展示商品信息&#xff0c;让用户在浏览商品的同时参与各种任务获得奖励&#xff0c;从而提升用户的活跃度和购买意愿。以下是多米优选卷轴模式系统开发的深度解析。 一、系统概述 多米优选卷轴模式源码系统旨在…