新版MQL语言程序设计:组合模式的原理、应用及代码实现
文章目录
- 一、什么组合模式
- 二、为什么需要组合模式
- 三、组合模式的实现原理
- 四、组合模式的应用场景
- 五、组合模式的代码实现
一、什么组合模式
组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
二、为什么需要组合模式
-
简化客户端代码:组合模式通过将对象组织成树形结构,使得客户端可以一致地对待单个对象和组合对象。客户端无需关心处理的是单个对象还是组合对象,从而简化了客户端的代码。
-
提供一致的操作接口:组合模式定义了一致的操作接口,使得客户端可以透明地操作单个对象和组合对象。客户端无需关心具体是哪个对象,只需要调用相同的方法即可。
-
支持递归组合:组合模式支持递归组合,即一个组合对象可以包含其他组合对象作为子节点。这样可以方便地处理复杂的层次结构,使得系统更加灵活和可扩展。
-
简化添加新对象:由于组合模式使用了统一的接口,添加新的对象变得非常简单。无论是添加单个对象还是组合对象,都只需要实现相同的接口即可。
-
提高代码复用性:组合模式可以通过递归组合的方式复用已有的对象。通过将对象组织成树形结构,可以灵活地复用已有的对象,从而提高代码的复用性。
三、组合模式的实现原理
- 定义一个抽象基类(Component):该类是组合中所有对象的共同接口,声明了一些操作方法,例如添加、删除、获取子节点等。
- 定义叶子类(Leaf):表示组合中的叶子节点,它没有子节点,实现了抽象基类中的操作方法。
- 定义容器类(Composite):表示组合中的容器节点,它可以包含子节点,实现了抽象基类中的操作方法。容器类中通常会有一个子节点列表用于存储子节点。
- 在容器类中实现对子节点的操作方法:例如添加、删除、获取子节点等。这些操作方法可以递归地调用子节点的相应方法,从而实现对整个树形结构的操作。
- 客户端使用组合模式:客户端可以通过抽象基类来统一对待单个对象和组合对象,从而简化了客户端的代码。客户端可以通过调用操作方法来对整个树形结构进行操作。
四、组合模式的应用场景
- 当需要表示对象的部分-整体层次结构,并且希望客户端能够以统一的方式处理单个对象和对象组合时,可以使用组合模式。
- 当希望忽略对象组合和单个对象之间的差异,统一对待它们时,可以使用组合模式。
- 当希望在不同层次上对对象进行操作,而不需要关心对象是单个对象还是对象组合时,可以使用组合模式。
五、组合模式的代码实现
//+------------------------------------------------------------------+
//| 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语言程序设计:组合模式的原理、应用及代码实现
文章目录 一、什么组合模式二、为什么需要组合模式三、组合模式的实现原理四、组合模式的应用场景五、组合模式的代码实现 一、什么组合模式 组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和…...
代码随想录算法训练营第25天 | 216.组合总和III ,17.电话号码的字母组合
回溯章节理论基础: 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 题目链接: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 🦀️。 在上一篇文章我们在macOS成功安装了rust。 一、vscode 安装rust相关插件 以下是一些常用的 Rust 开发插件…...
高斯消去法 | LU分解 | PA=LU分解(MatLab)
一、问题描述 利用高斯消去法,LU 分解及PALU 分解求解非线性方程组。 二、实验目的 掌握高斯消去法、LU 分解、PALU 分解的算法原理;编写代码实现利用高斯消去法、LU 分解、PALU 分解来求解线性方程组。 三、实验内容及要求 1. 利用顺序高斯消去法求…...
Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号
Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号 code review! 文章目录 Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号1.expect2.bash 1.expect 在Expect脚本中,你可以使用expect来监听程序输出,…...
项目02《游戏-12-开发》Unity3D
基于 项目02《游戏-11-开发》Unity3D , 任务:实现场景怪物自动巡航 , 首先在场景中创建小球命名为路径点WayPoint0, 取消小球的碰撞器Collider, 再复制两个改名为WayPoint1 和 WayPoint2 , 在…...
记一次面试题
1.Php 私有化包(composer)的部署 1. 创建你的PHP包 确定你的包的功能和命名空间。 创建一个新的目录并初始化一个Git仓库。 使用composer init命令创建一个composer.json文件,并定义你的包名、版本、依赖等信息。 2. 开发并测试你的包 在本地…...
Rust入门2——随机数
文章目录 一、生成随机数二、比较两个数相等 简单列出两个Rust的小例子 一、生成随机数 在Cargo.toml的dependencies中引入rand,指定rand的版本 [dependencies] rand "^0.3.14"之后在主函数中调用rand函数,生成随机数 use rand::Rng; f…...
c#: 表达式树的简化
环境: .net 6 一、问题? 有下面的表达式: var nums new List<int> { 1, 2, 3 }; Expression<Func<int, bool>> exp i > i > nums.Max();我们知道,它其实就是:exp i > i > 3; 那么…...
13. UE5 RPG限制Attribute的值的范围以及生成结构体
前面几章,我们实现了通过GameplayEffect对Attribute值的修改,比如血量和蓝量,我们都是有一个最大血量和最大蓝量去限制它的最大值,而且血量和蓝量最小值不会小于零。之前我们是没有实现相关限制的,接下来,我…...
UE4运用C++和框架开发坦克大战教程笔记(十九)(第58~60集)完结
UE4运用C和框架开发坦克大战教程笔记(十九)(第58~60集)完结 58. 弹窗显示与隐藏59. UI 面板销毁60. 框架完成与总结 58. 弹窗显示与隐藏 这节课我们先来补全 TransferMask() 里对于 Overlay 布局类型面板的遮罩转移逻辑ÿ…...
ModuleNotFoundError: No module named ‘_ctypes‘报错解决方案
1、须命令安装libbffi-devel软件包: yum install libffi-devel -y2、安装完后再重装python3,无须卸载 找到之前的python3安装包,如果安装包删除了通过 history | grep python命令找到最初安装时的包下载的命令下载,保证版本一样&…...
【服务器数据恢复】服务器RAID模块硬件损坏的数据恢复案例
服务器数据恢复环境&故障: 某品牌服务器中有一组由数块SAS硬盘组建的RAID5磁盘阵列,服务器操作系统是WINDOWS SERVER,服务器中存放企业数据,无数据库文件。 服务器出故障之前出现过几次意外断电的情况,服务器断电…...
spring boot3x登录开发-上(整合jwt)
⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 🌊山高路远,行路漫漫,终有归途。 目录 前置条件 jwt简介 导依赖 编写jwt工具类 1.配置项直接嵌入代码,通过类名.静态方法使用 2.配置项写到…...
git 克隆拉取代码出现私钥权限问题。
问题反馈: 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示例 一、引言 卷积编码,作为数字通信领域中的一项…...
揭开Markdown的秘籍:标题|文字样式|列表
🌈个人主页:聆风吟 🔥系列专栏:Markdown指南、网络奇遇记 🔖少年有梦不应止于心动,更要付诸行动。 文章目录 📋前言一. ⛳️Markdown 标题二. ⛳️Markdown 文字样式2.1 🔔斜体2.2 &…...
移动最小二乘法
移动最小二乘法(Moving Least Square,MLS)主要应用于曲线与曲面拟合,该方法基于紧支撑加权函数(即函数值只在有限大小的封闭域中定义大于零,而在域外则定义为零)和多项式基函数,通过…...
【LeetCode】37. 解数独(困难)——代码随想录算法训练营Day30
题目链接:37. 解数独 题目描述 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&…...
VUE学习——属性绑定
属性绑定,就是给html添加id、class这样类似的操作。 <template><div v-bind:id"dynamicId"><div v-bind:class"dynamicClass">Test</div></div> </template><script>export default{data(){return{…...
【Midjourney批量生成黄金工作流】:20年AI工程实战总结的7步标准化流水线(附可复用Prompt模板库)
更多请点击: https://intelliparadigm.com 第一章:Midjourney批量生成工作流的底层逻辑与范式演进 Midjourney 的批量生成并非简单重复调用 /imagine,其本质是围绕提示工程(Prompt Engineering)、状态管理(…...
【工业视觉】基于序列图像动态特征提取的熔炼结晶过程建模与量化分析
1. 工业视觉在熔炼结晶过程中的核心价值 我第一次接触工业视觉在熔炼结晶中的应用是在2018年一个铜冶炼项目。当时工厂老师傅们还在用肉眼观察结晶状态,不仅效率低下,而且不同操作员的判断标准差异能达到15%。这种主观性带来的工艺波动直接影响了产品质量…...
BQ34Z100-G1电量计配置不求人:用咸鱼EV2400+BqStudio完成电池组参数学习的保姆级教程
BQ34Z100-G1电量计配置实战:从零搭建高精度电池管理系统 在新能源和储能系统蓬勃发展的今天,精确的电池电量计量已成为电池管理系统(BMS)的核心竞争力。德州仪器(TI)的BQ34Z100-G1阻抗跟踪电量计凭借其出色的精度和稳定性,在工业储能、电动工…...
3步掌握:如何用HTML转Figma工具实现网页设计稿快速转换
3步掌握:如何用HTML转Figma工具实现网页设计稿快速转换 【免费下载链接】figma-html Convert any website to editable Figma designs 项目地址: https://gitcode.com/gh_mirrors/fi/figma-html 你是否曾羡慕某个网站的布局设计,却苦于无法快速将…...
中小团队在ubuntu服务器利用taotoken管理多项目api密钥与用量
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 中小团队在 Ubuntu 服务器利用 Taotoken 管理多项目 API 密钥与用量 在 Ubuntu 服务器上运行多个 AI 实验项目是许多中小型技术团队…...
Vue2项目里,如何用DHTMLX Gantt实现任务搜索、今日线定位和视图切换?这些实用功能我帮你搞定了
Vue2项目中DHTMLX Gantt三大进阶功能实战:搜索、今日线与视图切换 在项目管理工具的开发中,甘特图作为核心可视化组件,其交互体验直接决定了用户的使用效率。本文将聚焦三个高频需求场景,手把手教你如何在已有DHTMLX Gantt集成的V…...
AbMole丨CL 316243:β3-肾上腺素受体激动剂,在代谢调控与能量消耗研究中的应用
CL 316243是一种高选择性的β3-肾上腺素受体(β3-AR)激动剂,其对β3-AR的选择性远高于β1-AR和β2-AR[1]。CL 316243(CAS No.:138908-40-4)通过激活β3-AR,刺激腺苷酸环化酶(AC&…...
实测taotoken多模型聚合端点的响应延迟与稳定性表现
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 实测taotoken多模型聚合端点的响应延迟与稳定性表现 作为开发者,在将大模型能力集成到应用时,除了功能本身…...
除了卸载浏览器,ADB还能帮你清理哪些OPPO手机预装软件?附完整包名清单
深度优化OPPO手机:ADB卸载非必要预装应用全指南 对于追求系统纯净度的OPPO手机用户而言,预装应用往往占据宝贵存储空间并消耗后台资源。本文将系统介绍如何利用Android Debug Bridge(ADB)工具精准管理ColorOS系统中的各类预装组件…...
设计工程化实践:将设计思维转化为开发者技能的工具探索
1. 项目概述:当设计思维遇上代码技能最近在GitHub上看到一个挺有意思的项目,叫Arthurescc/design-fusion.skill。光看这个名字,就让我这个在设计和开发交叉领域摸爬滚打了十来年的老手眼前一亮。“Design Fusion”直译是“设计融合”…...
