组合模式(结构型)

目录

一、前言

二、透明组合模式

三、安全组合模式

四、总结


一、前言

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

        组合模式由以下角色组成:

Component(抽象组件):

一般是接口或者抽象类,是叶子构件和容器构件对象声明接口,抽象出访问以及管理子构件的方法,可以看做是根节点

Leaf(叶子结点):

在组合中表示叶子节点对象,叶子节点没有子节点,也就没有子构件

Composite(复合节点):

复合节点可以包含子节点,子节点可以是叶子节点,也可以是其他复合节点。可以看做是树枝节点

        整个组合模式的结构图:

二、透明组合模式

        组合模式分为透明和安全两种方式,在透明方式中,抽象组件中会声明所有类中的方法,客户端无法区别树叶对象和树枝对象,对客户端是透明的。但在树叶节点中,本来没有添加、删除放大,但却要实现它,是没有意义的。

        比如公司组织建构,公司有总公司,总公司下有财务部门、技术部门等,还有分公司,分公司也有财务部门,技术部门等。如果按照传统方式,总公司的财务部门、技术部门等需要代码实现,分公司的财务部门、技术部门也需要代码实现,但现实中这些部门的职责差不多,分公司其实可以复用总公司的财务部门、技术部门类。

        根据组合模式,我们便有以下代码实现:

        抽象组件Component类,即根节点:

public abstract class Component {abstract void add(Component component);abstract void remove(Component component);abstract void display(int depth);abstract void operation();
}

        复合节点Composite类,即树枝节点:

public class Composite extends Component{private List<Component> children = new ArrayList<>();private String name;public Composite(String name) {this.name = name;}@Overridevoid add(Component component) {children.add(component);}@Overridevoid remove(Component component) {children.remove(component);}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);for (Component component : children) {component.display(depth + 1);}}@Overridevoid operation() {for (Component component : children){component.operation();}}
}

        叶子节点财务部门LeafOne类:

public class LeafOne extends Component{private String name;public LeafOne(String name) {this.name = name;}@Overridevoid add(Component component) {}@Overridevoid remove(Component component) {}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "财务操作");}
}

        叶子节点财务部门LeafTwo类:

public class LeafTwo extends Component{private String name;public LeafTwo(String name) {this.name = name;}@Overridevoid add(Component component) {}@Overridevoid remove(Component component) {}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "技术操作");}
}

        客户端调用类:

public class Client {public static void main(String[] args) {Component component = new Composite("北京总公司");component.add(new LeafOne("北京总公司财务部门"));component.add(new LeafTwo("北京总公司技术部门"));Component component1 = new Composite("上海分公司");component1.add(new LeafOne("上海分公司财务部门"));component1.add(new LeafTwo("上海分公司技术部门"));component.add(component1);Component component2 = new Composite("深圳分公司");component2.add(new LeafOne("深圳分公司财务部门"));component2.add(new LeafTwo("深圳分公司技术部门"));component.add(component2);System.out.println("公司架构:");component.display(1);System.out.println("职能:");component.operation();}
}

        运行结果:

三、安全组合模式

        相较于透明方式的组合模式,安全方式主要在抽象组件中不包含添加、删除操作,客户端调用中区分复合节点和叶子节点。

        抽象组件Component类:

public abstract class Component {abstract void display(int depth);abstract void operation();
}

        复合节点Composite类:

public class Composite extends Component{private List<Component> children = new ArrayList<>();private String name;public Composite(String name) {this.name = name;}public void add(Component component) {children.add(component);}public void remove(Component component) {children.remove(component);}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);for (Component component : children) {component.display(depth + 1);}}@Overridevoid operation() {for (Component component : children){component.operation();}}
}

        叶子节点财务部门LeafOne类:

public class LeafOne extends Component {private String name;public LeafOne(String name) {this.name = name;}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "财务操作");}
}

        叶子节点财务部门LeafTwo类:

public class LeafTwo extends Component{private String name;public LeafTwo(String name) {this.name = name;}@Overridevoid display(int depth) {System.out.println("深度:" + depth + " 名称:" + name);}@Overridevoid operation() {System.out.println(name + "技术操作");}
}

        客户端调用:

public class Client {public static void main(String[] args) {Composite composite = new Composite("北京总公司");composite.add(new LeafOne("北京总公司财务部门"));composite.add(new LeafTwo("北京总公司技术部门"));Composite composite1 = new Composite("上海分公司");composite1.add(new LeafOne("上海分公司财务部门"));composite1.add(new LeafTwo("上海分公司技术部门"));composite.add(composite1);Composite composite2 = new Composite("深圳分公司");composite2.add(new LeafOne("深圳分公司财务部门"));composite2.add(new LeafTwo("深圳分公司技术部门"));composite.add(composite2);System.out.println("公司架构:");composite.display(1);System.out.println("职能:");composite.operation();}
}

        运行结果:

四、总结

        优点与缺点

优点:

1、高层模块(客户端)调用简单。组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码

2、节点自由增加,更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”

缺点:

1、在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

2、设计较复杂,客户端需要花更多时间理清类之间的层次关系

3、不容易限制容器中的构件

4、不容易用继承的方法来增加构件的新功能

        使用场景:

        当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式。      

        Spring中IOC就使用到组合模式,通过将组件组合成树形结构,实现了对象的依赖关系管理和生命周期控制。比如Spring中的CompositeCacheManager,Spring用来管理多个CacheManager的复合类。

文件系统:

组合模式可以用来表示文件系统的层次结构,使得客户端可以以统一的方式操作文件和文件夹,例如创建、删除、移动等。

组织机构:

组合模式可以用于表示组织机构的层次结构,例如公司的组织结构可以以树形结构来表示,根节点表示公司,子节点表示部门,叶子节点表示员工。使用组合模式可以统一地管理公司的组织结构,例如添加、删除部门或员工,查找某个部门的员工等。

图形界面控件:

图形界面中的控件可以被看作是一个层次结构,例如窗口控件可以包含按钮控件和文本框控件,按钮控件又可以包含图片控件等。组合模式可以用来表示控件的层次结构,使得客户端可以以统一的方式操作控件,例如添加、删除、遍历等。

菜单和菜单项:

在图形界面中,菜单可以包含菜单项,菜单项可以是子菜单或者普通的操作项。组合模式可以用来表示菜单和菜单项的层次结构,使得客户端可以以统一的方式操作菜单和菜单项,例如添加、删除、遍历等。

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

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

相关文章

SpringSecurity源码分析(RemeberMe)

RememberMeServices RememberMeServices 记住我的服务的接口 可以重写实现自己的记住我 public interface RememberMeServices { //建议 org. springframework. security. authentication. RememberMeAuthenticationToken 在大多数情况下使用它&#xff0c;因为它具有相应的身份…

词袋法TFIDF

Tf-idf⽂本特征提取 TF-IDF的主要思想是&#xff1a;如果某个词或短语在⼀篇⽂章中出现的概率⾼&#xff0c;并且在其他⽂章中很少出现&#xff0c;则认为此词或者短语具有很好的类别区分能⼒&#xff0c;适合⽤来分类。TF-IDF作⽤&#xff1a;⽤以评估⼀字词对于⼀个⽂件集或…

OpenAI 发布 AI 生成图片检测器;Meta 推出 AI 广告创意工具;Google 正式发布 Pixel 8a,主打 AI

OpenAI 发布 AI 生成图片检测器 OpenAI 昨日官宣推出专用的 AI 监测工具&#xff0c;用于监测图片是否由其旗下 AI 图片生成工具 DALL-E 生成&#xff0c;准确率高达 98.8%。 不过该公司表示&#xff0c;这个检测工具并非旨在检测 Midjourney 和 Stability 等其他流行生成器生…

安卓使用Fiddler抓包 2024

简介 最近试了一下安卓使用fiddler 抓包&#xff0c;发现https包基本都会丢失。原因是Anandroid 7版本针对ssl安全性做了加强&#xff0c;不认可用户的证书。我们要做的就是把fiddler导出的证书进过处理后放置到系统证书目录下面&#xff0c;这样才能抓包https请求。 这里使用…

https介绍,加密解密(举例+必要性,对称/非对称加密介绍),数字摘要/指纹(介绍,应用(session id,网盘的秒传功能))

目录 https 引入 介绍 加密解密层 介绍 没有绝对的安全 使用ssl的弊端 加密解密 概念 加密 解密 秘钥 举例 现实中 网络中 加密的必要性 常见加密方式 对称加密 特点 非对称加密 特点 数字摘要/指纹 介绍 应用 session id 百度网盘的秒传功能 https …

21_Scala集合_可变数组ArrayBuffer

文章目录 ArrayBuffer1.创建可变数组ArrayBuffer2.增加数据3.删除数据4.修改数据5.查询数据Appendix ArrayBuffer ArrayBuffer可变数组–感觉优点类似于Java的ArrayList 1.创建可变数组ArrayBuffer –请注意下面的mutable import scala.collection.mutable.ArrayBuffer //m…

DuDuTalk:4G桌面拾音设备在银行网点服务场景的应用价值

随着科技的飞速发展&#xff0c;银行业也在不断地寻求创新以提高服务质量和效率。在这个过程中&#xff0c;4G桌面拾音设备作为一种新型的智能设备&#xff0c;其在银行网点服务场景中的应用价值逐渐凸显出来。本文将从多个角度探讨4G桌面拾音设备在银行网点服务场景的应用价值…

英语学习笔记6——What make is it?

What make is it? 它是什么牌子的&#xff1f; make n.&#xff08;产品的&#xff09;品牌名称    v. 制作 区别&#xff1a;model n.&#xff08;产品的&#xff09;型号       n. 模型       n. 模特 make 指的是大的品牌名称&#xff0c; model 是旗下产品…

OpenHarmony 实战开发——南向统一编译的docker镜像来了

由于我自己的南向设备开发平台的需求&#xff0c;我将当前几个不同的 docker 镜像版本进行了整合&#xff0c;经过一段时间的攻关和验证&#xff0c;目前整合已完成&#xff0c;新版本的 Dockerfile 如下&#xff0c;这个不是公共需求&#xff0c;所以没有提交主干&#xff0c;…

Web APIs 学习归纳8---移动端特效

上一节学习了PC端的特效&#xff0c;现在学习移动端的特效。 一、移动端触屏事件 1.1 触屏事件概述 移动端浏览器兼容性较好&#xff0c;我们不需要考虑以前 JS 的兼容性问题&#xff0c;可以放心的使用原生 JS 书写效果&#xff0c;但是移动 端也有自己独特的地方。比如触屏…

容联云孔淼:大模型落地与全域营销中台建设

近日&#xff0c;由金科创新社主办的2024区域性商业银行数智化转型研讨会顺利召开&#xff0c; 容联云产业数字云事业群副总经理、诸葛智能创始人孔淼受邀出席&#xff0c;并分享数智化转型实践经验。 他分享了容联云两大核心产品&#xff0c;“大模型应用容犀Copilot”在金融营…

TypeScript 基础学习笔记:interface 与 type 的异同

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 TypeScript 学习笔记&#xff1a;interface 与 type 的异同&#x1f3a3; 引言&#x1f680; 快速入门1️⃣ Interface&#xff08;接口&#xff09;&#x1f4cb; 定义&#x1f91d; 实现&#x1f4a1; 特点 2️⃣ Type Al…

Android 高版本实现沉浸式状态栏

目前实现的android高版本沉浸式状态栏分为两类&#xff1a; 1、是纯透明状态栏&#xff1b; 2、是纯透明状态栏&#xff0c;但是状态栏字体是黑色&#xff1b; 将状态栏的代码封装到BaseActivity中更方便使用&#xff1a; BaseActivity: public abstract class BaseActivit…

AI一键换装超强电商生产力工具下载

支持win版本&#xff0c;对电脑硬件有一定的要求。建议固态硬盘留足至少30 G的空间&#xff0c;显卡n卡显存至少4G。一些低端独立显卡可能还不如高配cpu集成。 程序文件比较大&#xff0c;因为涉及到大型模型。 下载链接在后面 下载链接&#xff1a; https://pan.baidu.com…

【Linux】如何定位客户端程序的问题

文章目录 1 客户端程序和服务端程序的差别2 问题类型2.1 崩溃(crash)2.2 CPU高2.3 内存高2.4 线程卡死 3 总结 1 客户端程序和服务端程序的差别 客户端程序是运行在终端上&#xff0c;通常都会与业务系统共存&#xff0c;而服务端程序通常会运行在单独的节点上&#xff0c;或者…

Shell编程之条件语句与case语句

目录 1.条件测试 1.1 文件测试 1.2 整数测试 1.3 字符串测试 1.4 逻辑测试 2.if语句 2.1 单分支if语句 2.2 双分支if语句 2.3 多分支if语句 3.case分支语句 1.条件测试 test命令 Shell环境根据命令执行后的返回状态值&#xff08;$?&#xff09;来判断是否执行成功…

找最大数字-第12届蓝桥杯国赛Python真题解析

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第60讲。 找最大数字&#…

你会拧螺丝吗?来看看如何拧紧螺丝?——SunTorque智能扭矩系统

智能扭矩系统-智能拧紧系统-扭矩自动控制系统-SunTorque 螺丝拧紧看似简单&#xff0c;却是一门需要技巧和耐心的技术活。很多人可能会认为&#xff0c;只要把螺丝旋进孔里&#xff0c;用力拧紧就可以了。但实际上&#xff0c;拧紧螺丝的过程远不止如此。在这篇文章中&#xf…

FPGA+DDR+SERDES+USB3.0单向传输机方案,数据只能单向传输,避免反向攻击,确保系统安全

FPGADDRSERDESUSB3.0方案&#xff0c;设备包含发送端接收端&#xff0c;物料上采用光纤通讯&#xff0c;数据只能单向传输&#xff0c;避免反向攻击&#xff0c;确保系统安全 客户应用:高安全、高可靠性要求的场景 主要性能: 1.支持USB3.0传输&#xff0c;实测可达到350MB/s 2.…

做安卓应用开发的我,转前端开发了

距离转前端开发已经快3个月了&#xff0c;现在自己也慢慢的熟悉了开发。 在2月份的时候。领导找我们移动小组的谈话&#xff0c;主要是关于转前端或者后端的问题。由于公司移动端的选型&#xff0c;对安卓原生的需求降低&#xff0c;问下我们转其他开发的需求。 我毫不犹豫的选…