当前位置: 首页 > news >正文

新版MQL语言程序设计:组合模式的原理、应用及代码实现

文章目录

    • 一、什么组合模式
    • 二、为什么需要组合模式
    • 三、组合模式的实现原理
    • 四、组合模式的应用场景
    • 五、组合模式的代码实现

一、什么组合模式

组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

二、为什么需要组合模式

  • 简化客户端代码:组合模式通过将对象组织成树形结构,使得客户端可以一致地对待单个对象和组合对象。客户端无需关心处理的是单个对象还是组合对象,从而简化了客户端的代码。

  • 提供一致的操作接口:组合模式定义了一致的操作接口,使得客户端可以透明地操作单个对象和组合对象。客户端无需关心具体是哪个对象,只需要调用相同的方法即可。

  • 支持递归组合:组合模式支持递归组合,即一个组合对象可以包含其他组合对象作为子节点。这样可以方便地处理复杂的层次结构,使得系统更加灵活和可扩展。

  • 简化添加新对象:由于组合模式使用了统一的接口,添加新的对象变得非常简单。无论是添加单个对象还是组合对象,都只需要实现相同的接口即可。

  • 提高代码复用性:组合模式可以通过递归组合的方式复用已有的对象。通过将对象组织成树形结构,可以灵活地复用已有的对象,从而提高代码的复用性。

三、组合模式的实现原理

  1. 定义一个抽象基类(Component):该类是组合中所有对象的共同接口,声明了一些操作方法,例如添加、删除、获取子节点等。
  2. 定义叶子类(Leaf):表示组合中的叶子节点,它没有子节点,实现了抽象基类中的操作方法。
  3. 定义容器类(Composite):表示组合中的容器节点,它可以包含子节点,实现了抽象基类中的操作方法。容器类中通常会有一个子节点列表用于存储子节点。
  4. 在容器类中实现对子节点的操作方法:例如添加、删除、获取子节点等。这些操作方法可以递归地调用子节点的相应方法,从而实现对整个树形结构的操作。
  5. 客户端使用组合模式:客户端可以通过抽象基类来统一对待单个对象和组合对象,从而简化了客户端的代码。客户端可以通过调用操作方法来对整个树形结构进行操作。

四、组合模式的应用场景

  1. 当需要表示对象的部分-整体层次结构,并且希望客户端能够以统一的方式处理单个对象和对象组合时,可以使用组合模式。
  2. 当希望忽略对象组合和单个对象之间的差异,统一对待它们时,可以使用组合模式。
  3. 当希望在不同层次上对对象进行操作,而不需要关心对象是单个对象还是对象组合时,可以使用组合模式。

五、组合模式的代码实现

//+------------------------------------------------------------------+
//| structure                                                        |
//+------------------------------------------------------------------+
//
//     |Client|----->|    Component    |*<------------------+
//                   |-----------------|                    |
//                   |Operation()      |                    | 
//                   |Add(Component)   |                    |
//                   |Remove(Component)|                    |
//                   |GetChild(int)    |                    |
//                            ^                             |
//                            |                             |
//                    +-------+-----------+                 |
//                    |                   |           nodes |
//              |   Leaf    |   |     Composite     |o------+
//              |-----------|   |-------------------|
//              |Operation()|   |Operation()        |
//                              | for all n in nodes|
//                              |  n.Operation()    |
//                              |Add(Component)     |
//                              |Remove(Component)  |
//                              |GetChild(int)      |
//
//+------------------------------------------------------------------+
//| typical object structure                                         |
//+------------------------------------------------------------------+
//
//                        +---->|aLeaf|
//                        |
//       |aComposite|-----+---->|aLeaf|         +---->|aLeaf|
//                        |                     |
//                        +---->|aComposite|----+---->|aLeaf|
//                        |                     |
//                        +---->|aLeaf|         +---->|aLeaf|
//
// 组件
class Component
{public:virtual void      Operation(void)=0;virtual void      Add(Component*)=0;virtual void      Remove(Component*)=0;virtual Component*   GetChild(int)=0;Component(void);Component(string);protected:string            name;
};
Component::Component(void) {}
Component::Component(string a_name):name(a_name) {}#define ERR_INVALID_OPERATION_EXCEPTION   1
// 向叶添加/删除组件时出现用户错误
// 表示>叶对象<合成
// 没有孩子
// 定义>行为>组合中的基本体对象
class Leaf:public Component
{public:void              Operation(void);void              Add(Component*);void              Remove(Component*);Component*        GetChild(int);Leaf(string);
};
void Leaf::Leaf(string a_name):Component(a_name) {}
void Leaf::Operation(void) {Print(name);}
void Leaf::Add(Component*) {SetUserError(ERR_INVALID_OPERATION_EXCEPTION);}
void Leaf::Remove(Component*) {SetUserError(ERR_INVALID_OPERATION_EXCEPTION);}
Component* Leaf::GetChild(int) {SetUserError(ERR_INVALID_OPERATION_EXCEPTION); return NULL;}// 定义>具有子级的组件的行为
// 存储>子组件
// 在组件接口中实现>子相关操作>
// 组合
class Composite:public Component
{public:void              Operation(void);void              Add(Component*);void              Remove(Component*);Component*        GetChild(int);Composite(string);~Composite(void);protected:Component*        nodes[];
};
Composite::Composite(string a_name):Component(a_name) {}
//+------------------------------------------------------------------+
//| participants > composite                                         |
//+------------------------------------------------------------------+
Composite::~Composite(void)
{int total = ArraySize(nodes);for (int i=0; i<total; i++){Component* i_node=nodes[i];if (CheckPointer(i_node)==1){delete i_node;}}
}
//+------------------------------------------------------------------+
//| participants > composite                                         |
//+------------------------------------------------------------------+
void Composite::Operation(void)
{Print(name);int total = ArraySize(nodes);for (int i=0; i<total; i++){nodes[i].Operation();}
}
//+------------------------------------------------------------------+
//| participants > composite                                         |
//+------------------------------------------------------------------+
void Composite::Add(Component *src)
{int size = ArraySize(nodes);ArrayResize(nodes,size+1);nodes[size] = src;
}
//+------------------------------------------------------------------+
//| participants > composite                                         |
//+------------------------------------------------------------------+
void Composite::Remove(Component *src)
{int find=-1;int total=ArraySize(nodes);for (int i=0; i<total; i++){if (nodes[i]==src){find=i;break;}}if (find>-1){ArrayRemove(nodes,find,1);}
}
//+------------------------------------------------------------------+
//| participants > composite                                         |
//+------------------------------------------------------------------+
Component* Composite::GetChild(int i)
{return nodes[i];
}
//+------------------------------------------------------------------+
//| interface for patterns                                           |
//+------------------------------------------------------------------+
interface ClientInterface 
{string Output(void);void Run(void);
};
//+------------------------------------------------------------------+
//| interface for patterns                                           |
//+------------------------------------------------------------------+
void Run(ClientInterface* client) //launches a pattern
{printf("---\n%s",client.Output()); //print pattern headerclient.Run(); //execute client collaborationsdelete client; //exit
}
// 通过组件接口操作组合中的对象
class Client:public ClientInterface
{public:string            Output(void);void              Run(void);
};
string Client::Output(void) {return __FUNCTION__;}
//+------------------------------------------------------------------+
//| collaborations                                                   |
//+------------------------------------------------------------------+
void Client::Run(void)
{Component* root=new Composite("root"); //make root//---make componentsComponent* branch1=new Composite(" branch 1");Component* branch2=new Composite(" branch 2");Component* leaf1=new Leaf("  leaf 1");Component* leaf2=new Leaf("  leaf 2");//---build treeroot.Add(branch1);root.Add(branch2);branch1.Add(leaf1);branch1.Add(leaf2);branch2.Add(leaf2);branch2.Add(new Leaf("  leaf 3"));//---checkprintf("tree:");root.Operation();//---change treeroot.Remove(branch1); //remove whole branch//---checkprintf("tree after removal of one branch:");root.Operation();//---finishdelete root;delete branch1;
}
//
void OnStart() 
{Run(new Composite::Client);
}
//+------------------------------------------------------------------+
//| output                                                           |
//+------------------------------------------------------------------+
//   Structural::Composite::Client::Output
//   tree:
//   root
//    branch 1
//     leaf 1
//     leaf 2
//    branch 2
//     leaf 2
//     leaf 3
//   tree after removal of one branch:
//   root
//    branch 2
//     leaf 2
//     leaf 3

相关文章:

新版MQL语言程序设计:组合模式的原理、应用及代码实现

文章目录 一、什么组合模式二、为什么需要组合模式三、组合模式的实现原理四、组合模式的应用场景五、组合模式的代码实现 一、什么组合模式 组合模式是一种结构型设计模式&#xff0c;它允许将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和…...

代码随想录算法训练营第25天 | 216.组合总和III ,17.电话号码的字母组合

回溯章节理论基础&#xff1a; https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 216.组合总和III 题目链接&#xff1a;https://leetcode.cn/problems/combination-sum-iii/ 思路: 本题就是在[1,2,3,4,5,6,7,…...

Rust 第一个rust程序Hello Rust️

文章目录 前言一、vscode 安装rust相关插件二、Cargo New三、vscode调试rustLLDB 前言 Rust学习系列。今天就让我们掌握第一个rust程序。Hello Rust &#x1f980;️。 在上一篇文章我们在macOS成功安装了rust。 一、vscode 安装rust相关插件 以下是一些常用的 Rust 开发插件…...

高斯消去法 | LU分解 | PA=LU分解(MatLab)

一、问题描述 利用高斯消去法&#xff0c;LU 分解及PALU 分解求解非线性方程组。 二、实验目的 掌握高斯消去法、LU 分解、PALU 分解的算法原理&#xff1b;编写代码实现利用高斯消去法、LU 分解、PALU 分解来求解线性方程组。 三、实验内容及要求 1. 利用顺序高斯消去法求…...

Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号

Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号 code review! 文章目录 Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号1.expect2.bash 1.expect 在Expect脚本中&#xff0c;你可以使用expect来监听程序输出&#xff0c;…...

项目02《游戏-12-开发》Unity3D

基于 项目02《游戏-11-开发》Unity3D &#xff0c; 任务&#xff1a;实现场景怪物自动巡航 &#xff0c; 首先在场景中创建小球命名为路径点WayPoint0&#xff0c; 取消小球的碰撞器Collider&#xff0c; 再复制两个改名为WayPoint1 和 WayPoint2 &#xff0c; 在…...

记一次面试题

1.Php 私有化包&#xff08;composer&#xff09;的部署 1. 创建你的PHP包 确定你的包的功能和命名空间。 创建一个新的目录并初始化一个Git仓库。 使用composer init命令创建一个composer.json文件&#xff0c;并定义你的包名、版本、依赖等信息。 2. 开发并测试你的包 在本地…...

Rust入门2——随机数

文章目录 一、生成随机数二、比较两个数相等 简单列出两个Rust的小例子 一、生成随机数 在Cargo.toml的dependencies中引入rand&#xff0c;指定rand的版本 [dependencies] rand "^0.3.14"之后在主函数中调用rand函数&#xff0c;生成随机数 use rand::Rng; f…...

c#: 表达式树的简化

环境&#xff1a; .net 6 一、问题&#xff1f; 有下面的表达式&#xff1a; var nums new List<int> { 1, 2, 3 }; Expression<Func<int, bool>> exp i > i > nums.Max();我们知道&#xff0c;它其实就是&#xff1a;exp i > i > 3; 那么…...

13. UE5 RPG限制Attribute的值的范围以及生成结构体

前面几章&#xff0c;我们实现了通过GameplayEffect对Attribute值的修改&#xff0c;比如血量和蓝量&#xff0c;我们都是有一个最大血量和最大蓝量去限制它的最大值&#xff0c;而且血量和蓝量最小值不会小于零。之前我们是没有实现相关限制的&#xff0c;接下来&#xff0c;我…...

UE4运用C++和框架开发坦克大战教程笔记(十九)(第58~60集)完结

UE4运用C和框架开发坦克大战教程笔记&#xff08;十九&#xff09;&#xff08;第58~60集&#xff09;完结 58. 弹窗显示与隐藏59. UI 面板销毁60. 框架完成与总结 58. 弹窗显示与隐藏 这节课我们先来补全 TransferMask() 里对于 Overlay 布局类型面板的遮罩转移逻辑&#xff…...

ModuleNotFoundError: No module named ‘_ctypes‘报错解决方案

1、须命令安装libbffi-devel软件包&#xff1a; yum install libffi-devel -y2、安装完后再重装python3&#xff0c;无须卸载 找到之前的python3安装包&#xff0c;如果安装包删除了通过 history | grep python命令找到最初安装时的包下载的命令下载&#xff0c;保证版本一样&…...

【服务器数据恢复】服务器RAID模块硬件损坏的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 某品牌服务器中有一组由数块SAS硬盘组建的RAID5磁盘阵列&#xff0c;服务器操作系统是WINDOWS SERVER&#xff0c;服务器中存放企业数据&#xff0c;无数据库文件。 服务器出故障之前出现过几次意外断电的情况&#xff0c;服务器断电…...

spring boot3x登录开发-上(整合jwt)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 jwt简介 导依赖 编写jwt工具类 1.配置项直接嵌入代码&#xff0c;通过类名.静态方法使用 2.配置项写到…...

git 克隆拉取代码出现私钥权限问题。

问题反馈&#xff1a; rootdd:~/android/boost-1.74-for-android-r20b# git clone https://github.com/liulilittle/boost-1.74-for-android-r20b.git Cloning into boost-1.74-for-android-r20b... WARNING: UNPROTECTED PRIVATE KEY FILE! Permissions 0777 for /root/…...

【5G NR】【一文读懂系列】移动通讯中使用的信道编解码技术-卷积码原理

目录 一、引言 二、卷积编码的发展历史 2.1 卷积码的起源 2.2 主要发展阶段 2.3 重要里程碑 三、卷积编码的基本概念 3.1 基本定义 3.2 编码器框图 3.3 编码多项式 3.4 网格图(Trellis)描述 四、MATLAB示例 一、引言 卷积编码&#xff0c;作为数字通信领域中的一项…...

揭开Markdown的秘籍:标题|文字样式|列表

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;Markdown指南、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️Markdown 标题二. ⛳️Markdown 文字样式2.1 &#x1f514;斜体2.2 &…...

移动最小二乘法

移动最小二乘法&#xff08;Moving Least Square&#xff0c;MLS&#xff09;主要应用于曲线与曲面拟合&#xff0c;该方法基于紧支撑加权函数&#xff08;即函数值只在有限大小的封闭域中定义大于零&#xff0c;而在域外则定义为零&#xff09;和多项式基函数&#xff0c;通过…...

【LeetCode】37. 解数独(困难)——代码随想录算法训练营Day30

题目链接&#xff1a;37. 解数独 题目描述 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&…...

VUE学习——属性绑定

属性绑定&#xff0c;就是给html添加id、class这样类似的操作。 <template><div v-bind:id"dynamicId"><div v-bind:class"dynamicClass">Test</div></div> </template><script>export default{data(){return{…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

用递归算法解锁「子集」问题 —— LeetCode 78题解析

文章目录 一、题目介绍二、递归思路详解&#xff1a;从决策树开始理解三、解法一&#xff1a;二叉决策树 DFS四、解法二&#xff1a;组合式回溯写法&#xff08;推荐&#xff09;五、解法对比 递归算法是编程中一种非常强大且常见的思想&#xff0c;它能够优雅地解决很多复杂的…...