设计模式之组合

组合模式介绍

一棵树结构

组合模式是把相似对象或方法组合成一组可被调用的结构树对象的设计思路。

组合模式不只是可以运用于规则决策树,还可以做服务包装将不同的接口进行组合配置,对外提供服务能力,减少开发成本。

组合模式的主要解决的是一系列简单逻辑节点或者扩展的复杂逻辑节点在不同结构的组织下,对于外部的调用是仍然可以非常简单的。

组合模式的结构

  • 组件  接口描述了树中简单项目和复杂项目所共有的操作。

  • 叶节点 是树的基本结构,它不包含子项目。一般情况下,叶节点最终会完成大部分的实际工作,因为它们无法将工作指派给其他部分。

  • 容器   又名组合,是包含叶节点或其他容器等子项目的单位。容器不知道其子项目所属的具体类,它只通过通用的接口与其子项目交互。容器接收到请求后会将工作分配给自己的子项目,处理中间结果,然后将最终结果返回客户端。

  • 客户端  通过组件接口与所有项目交互。因此,客户端能以相同方式与树状结构中的简单或复杂项目交互。

组合模式的应用场景

  • 当业务是需要实现树状对象结构,可以使用组合模式。

组合模式提供两种共享公共接口的基本元素类型:简单叶节点复杂容器。容器中可以包含叶节点和其他容器。这样就可以构建树状嵌套递归对象结构。

  • 当希望客户端代码以相同方式处理简单和复杂元素,可以使用组合模式

组合模式中定义的所有元素共用同一个接口。正式由于这接口,客户端不必在意其所使用的对象的具体类。

组合模式的优缺点

优点:

1、可以利用多态和递归机制更方便地使用复杂树结构

2、开闭原则,无需更改现有代码,就可以在应用中添加新元素,使其成为对象树的一部分。

缺点:

1、对于功能差异大的类,提供公共接口或许会有困难。

实现方式

1、确保应用的核心模型能够以树状结构表示,尝试将其分解为简单元素和容器。其中容器必须同时包含简单元素和其他容器。

2、声明组件接口及其一系列方法,这些方法对简单和复杂元素都有意义。

3、创建一个叶节点类表示简单元素,程序中可以有多个不同的叶节点类。

4、创建一个容器类表示复杂元素。在该类中,创建一个数组成员变量来存储对于其子元素的引用。该数组必须能够同时保存叶节点和容器,因此请确保将其声明为组合接口类型。

实现组件接口方法时,记住容器应该将大部分工作交给其子元素来完成。

5、在容器中定义添加和删除子元素的方法。

这些操作可在组件接口中声明。会违背“接口隔离原则”,因为叶节点类中的这些方法为空。但是可以让客户端无差别地访问所有元素,即使是组成树状结构的元素。

Demo

    /// <summary>/// 为简单对象和复杂对象声明了通用操作/// </summary>abstract class Component{public Component() {}/// <summary>/// 操作变量/// </summary>/// <returns></returns>public abstract string Operation();public virtual void Add(Component component) {throw new NotImplementedException();}public virtual void Remove(Component component) {throw new NotImplementedException();}/// <summary>/// 是否是复合/// </summary>/// <returns></returns>public virtual bool IsComposite() {return true;}}
    /// <summary>/// 叶/// </summary>class Leaf:Component{public override string Operation(){return "Leaf";}public override bool IsComposite(){return false;}}
    /// <summary>/// 复合对象(里面既包含叶又包含小复合对象)/// </summary>class Composite:Component{protected List<Component> _children = new List<Component>();public override void Add(Component component){this._children.Add(component);}public override void Remove(Component component){this._children.Remove(component);}public override string Operation(){int i = 0;string result = "包含的分支都有那些:";foreach (var component in _children){result += component.Operation();if(i!=_children.Count-1){result += "+";}i++;}return result + ")";}}
    /// <summary>/// 客户端/// </summary>class Client{/// <summary>/// 组件调用接口   叶子调用/// </summary>/// <param name="leaf"></param>public void ClientCode(Component leaf) {Console.WriteLine("Result:"+leaf.Operation());}/// <summary>/// 在基组件类中,客户端可以与任何组件,简单和复杂的对象交互,不依赖具体的类/// </summary>/// <param name="c1"></param>/// <param name="c2"></param>public void ClientCode2(Component c1,Component c2){if (c1.IsComposite()){c1.Add(c2);}Console.WriteLine("Result:"+c1.Operation());}}
    class Program{static void Main(string[] args){Client client = new Client();Leaf leaf = new Leaf();Console.WriteLine("调用叶子......");client.ClientCode(leaf);Console.WriteLine("---------------");Composite tree = new Composite();Composite branch1 = new Composite();branch1.Add(new Leaf());branch1.Add(new Leaf());Composite branch2 = new Composite();branch2.Add(new Leaf());tree.Add(branch1);tree.Add(branch2);Console.WriteLine("调用复杂对象......");client.ClientCode(tree);Console.WriteLine("---");client.ClientCode2(tree,leaf);Console.ReadKey();}}
计算结果显示

从计算结果可以看出,当第一次只调用叶子时,结果就只显示叶子,也就是简单元素,当第二次声明实例化复杂容器(包含叶子和别的容器)时,输出结果也可以把所有声明实例的容器中的所有叶子和子容器都输出显示。

其实对于我们业务来说,需要把握好业务的逻辑看到底需要并适合那种模式,这样才能不为了模式而模式代码。

小寄语

人生短暂,我不想去追求自己看不见的,我只想抓住我能看的见的。

我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发  谢谢。

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

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

相关文章

leetcode中的状态机类型的题目

1 总结 一般是涉及到多个状态之间的转换&#xff0c;需要定义一个具有多个枚举值的变量&#xff0c;各个状态之间通过各种条件互相变化 2 LC57. 插入区间 2.1 解析 先是要确定新区间插入到哪一个位置&#xff08;也有可能&#xff09;&#xff0c;插入后需要确定这个区间是否…

如何用Python进行数据探索,探索竞赛优胜方案?

全世界只有3.14 % 的人关注了 青少年数学之旅 AI这个词相信大家都非常熟悉&#xff0c;近几年来人工智能圈子格外热闹&#xff0c;光是AlphoGo就让大家对它刮目相看。 随着大数据时代信息科技的快速发展&#xff0c;各种各样的数据充斥着我们的生活。而我们又当如何有效利用数据…

联想ThinkPad笔记本广告向苹果MacBook Air开战

联想ThinkPad笔记本广告向苹果MacBook Air开战 [url]http://www.sina.com.cn[/url] 2008年03月24日 07:21 新浪科技联想ThinkPad X300笔记本广告&#xff0c;暗讽苹果MacBook AirMacbook Air最厚的地方仅有1.94cm&#xff0c;边缘仅0.4cm视频&#xff1a;ThinkPad X300对比Mac…

基于 gRPC 和 .NET Core 的服务器流

原文&#xff1a;https://bit.ly/3lpz8Ll作者&#xff1a;Chandan Rauniyar翻译&#xff1a;精致码农-王亮早在 2019 年&#xff0c;我写过《用 Mapbox 绘制位置数据》一文&#xff0c;详细介绍了我如何通过简单的文件上传&#xff0c;用 Mapbox 绘制约 230 万个位置点。本文介…

jQuery入门[2]-选择器[转]

jQuery之所以令人爱不释手&#xff0c;在于其强大的选择器表达式令DOM操作优雅而艺术。jQuery的选择符支持id,tagName,css1-3 expressions,XPath&#xff0c;参见&#xff1a;http://docs.jquery.com/SelectorsDEMO:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tran…

是个狠角色。。 | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源洱海弥&#xff0c;侵权删&#xff09;

构建Windows Server 2008虚拟实验室

在阅读新闻稿时&#xff0c;有很多文章和指导&#xff0c;都有一些帮助&#xff0c;但却没有针对Windows Server 2008的手把手经验可供参考。对管理员来说&#xff0c;要熟悉这个服务器系统的最好方法是确定它的特性是如何给他们的Windows环境带来便利。 先前我描述了如何方便地…

eclipse配置tomcat 和JRE环境

配置JRE环境&#xff0c;通俗点讲就是添加一个不同版本的jdk window——preferences——java——installed jres 点击add添加 选择standard VM 择一个本机正确的jdk路径 name和下面lib加载都是系统自动完成的 选择好路径后 点 finish就ok了 配置tomcat window——preferen…

为什么我的 Func 如此之慢?

咨询区 Ricky G&#xff1a;我正在给项目做性能和代码优化&#xff0c;比如将重复的代码提炼成到一个可重用的方法中&#xff0c;为了能够达到可重用目的&#xff0c;我用 Func<T> 作为方法参数。public int Calculate(Func<int> expr){return expr();}当我用 Benc…

[转载MSDN]IIS 7.0中的Live Smooth Streaming -入门

IIS Live Smooth Streaming - 测试版是Internet 信使服务 (IIS) 7.0的一个扩展&#xff0c;它能提供流畅的视频流媒体&#xff0c;并且可以根据客户端的网络带宽和CPU的执行能力的改变&#xff0c;随时的调整视频质量。 IIS Live Smooth Streaming允许Microsoft Silverlight客户…

为啥饮料瓶大都是圆的,牛奶盒却是方的?

全世界只有3.14 % 的人关注了青少年数学之旅一提起喝饮料和牛奶你们是不是就来精神了但是喝了这么久的饮料你有没有想过一个问题为什么饮料瓶一般都是圆的&#xff1f;而牛奶盒却是方的&#xff1f;有的人可能会说饮料瓶要拿在手上当然是圆的舒服啊拿着一个方形的饮料瓶时间长了…

Docker最全教程之使用Docker搭建Java开发环境

前言 Java是一门面向对象的优秀编程语言&#xff0c;市场占有率极高&#xff0c;但是在容器化实践过程中&#xff0c;发现官方支持并不友好&#xff0c;同时与其他编程语言的基础镜像相比&#xff08;具体见各语言镜像比较&#xff09;&#xff0c;确实是非常臃肿。 Java [J…

OrganicsDelivery总结

一、UserControl调用所在页面的其他内容&#xff08;代理实现&#xff09; UserControl代码 Codeusing System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;…

面试官:Redis 内存数据满了,会宕机吗?

背景Redis 数据库内存数据满了&#xff0c;会宕机吗&#xff1f;答案是&#xff1a;不会让它出现存满的情况&#xff0c;在使用Redis的时候我们要配置Redis能使用的最大的内存大小&#xff0c;存到一定容量的时候还有Redis的内存淘汰策略呢&#xff0c;还有LRU算法进行淘汰&…

你爱我吗? | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源你这样真的很机车诶&#xff0c;侵权删&#xff09;

Java开发和嵌入式开发该如何选择

首先&#xff0c;Java开发和嵌入式开发都是目前IT行业内比较常见的开发岗位&#xff0c;也都有大量的从业人员&#xff0c;所以从就业的角度来看&#xff0c;学习Java开发和嵌入式开发都是不错的选择。Java语言的应用领域包括Web开发、Android开发和大数据开发等领域&#xff0…

小米和腾讯的.NET笔面试题哪个更难?可自测附答案

统计了下&#xff0c;当下正在招.NET的大厂有腾讯、京东、唯品会、阿里、百度、华为、小米、网易、特斯拉等。进大厂、拿高薪、享福利&#xff0c;应该是.NET程序员普世梦想了。金九银十将至&#xff0c;还不赶紧刷题准备&#xff1f;即使等金三银四&#xff0c;下面这些笔面试…

熬夜变傻有科学依据,人类睡觉时会被“洗脑”,科学家首次拍下全程

全世界只有3.14 % 的人关注了青少年数学之旅你睡着的时候&#xff0c;真的被洗了脑。这次&#xff0c;波士顿大学的科学家们&#xff0c;史无前例地拍下了清洗过程&#xff1a;红色是血液&#xff0c;蓝色是脑脊液。厉害的是从前没有发现过&#xff0c;血液会周期性地大量流出大…

程序员的人生

今天在网上看到这么一张图片&#xff0c;让人吃惊不小&#xff0c;我也是一名典型的学生出身的程序员在这个行业做了也接近三年了&#xff0c;也曾经犹豫过&#xff0c;曾经迷茫过&#xff0c;曾经思考过自己以后的人生&#xff0c;也是几乎和下面这张图片的经历一致&#xff0…

到家自动充电,拜拜充电线!东京大学开发自动充电房间,能量成为“与空气一样的东西”...

全世界只有3.14 % 的人关注了青少年数学之旅每天下班回家第一件事&#xff0c;是不是给手机充电&#xff1f;但是充电线在哪&#xff0c;你找得到吗&#xff1f;如果现在告诉你&#xff0c;一回到家&#xff0c;手机就能自动充电&#xff0c;简直就是整理苦手的救星&#xff01…