二十三种设计模式第十二篇--组合模式

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

在组合模式中,有两种类型的对象:叶子对象和组合对象。叶子对象表示树结构中的叶子节点,它没有子节点。组合对象表示树结构中的非叶子节点,它可以包含其他的组合对象和叶子对象。

组合模式的核心思想是将单个对象和组合对象统一对待,使得用户可以一致地使用它们。用户可以通过统一的接口来操作单个对象和组合对象,而不需要关心它们的具体类型。

组合模式的应用场景包括:

当需要表示一个对象的整体-部分层次结构时,可以使用组合模式。例如,文件系统中的文件和文件夹可以使用组合模式来表示。

当希望用户可以一致地对待单个对象和组合对象时,可以使用组合模式。例如,图形界面中的控件可以使用组合模式来表示。

当希望将一组相似的对象作为一个整体来处理时,可以使用组合模式。例如,菜单中的菜单项可以使用组合模式来表示。

总结起来,组合模式通过将对象组合成树形结构来表示整体-部分的层次结构,使得用户可以一致地对待单个对象和组合对象。它适用于需要表示整体-部分层次结构的场景,以及需要将一组相似的对象作为一个整体来处理的场景。

在这里插入图片描述
本篇文章中例举一个简单的组合模,根据上述UML图,我们来设计代码。

public class Employee {
   private String name;
   private String dept;
   private int salary;
   //下属列表
   private List<Employee> subordinates;
 
   //构造函数
   public Employee(String name,String dept, int sal) {
      this.name = name;
      this.dept = dept;
      this.salary = sal;
      subordinates = new ArrayList<Employee>();
   }
 
   public void add(Employee e) {
      subordinates.add(e);
   }
 
   public void remove(Employee e) {
      subordinates.remove(e);
   }
 
   public List<Employee> getSubordinates(){
     return subordinates;
   }
 
   public String toString(){
      return ("Employee :[ Name : "+ name 
      +", dept : "+ dept + ", salary :"
      + salary+" ]");
   }   
}

public class CompositePatternDemo {
   public static void main(String[] args) {
      Employee CEO = new Employee("John","CEO", 30000);
 
      Employee headSales = new Employee("Robert","Head Sales", 20000);
      Employee headMarketing = new Employee("Michel","Head Marketing", 20000);
 
      Employee clerk1 = new Employee("Laura","Marketing", 10000);
      Employee clerk2 = new Employee("Bob","Marketing", 10000);
 
      Employee salesExecutive1 = new Employee("Richard","Sales", 10000);
      Employee salesExecutive2 = new Employee("Rob","Sales", 10000);

      //CEO的下一级
      CEO.add(headSales);
      CEO.add(headMarketing);
      // 销售主管的下一级
      headSales.add(salesExecutive1);
      headSales.add(salesExecutive2);
      //市场主管的下一级
      headMarketing.add(clerk1);
      headMarketing.add(clerk2);
 
      //打印该组织的所有员工
      System.out.println(CEO); 
      for (Employee headEmployee : CEO.getSubordinates()) {
         System.out.println("\t"+headEmployee);
         for (Employee employee : headEmployee.getSubordinates()) {
            System.out.println("\t\t"+employee);
         }
      }        
   }
}

运行效果:
在这里插入图片描述
实际上组合模式是对一种整体和部分的关系,组合模式可以使得用户对单个对象和组合对象之间具有一致性。

拓展:

在现实生活中,存在很多“部分-整体”的关系,例如,大学中的部门与学院、总公司中的部门与分公司、学习用品中的书与书包、生活用品中的衣服与衣柜、以及厨房中的锅碗瓢盆等。在软件开发中也是这样,例如,文件系统中的文件与文件夹、窗体程序中的简单控件与容器控件等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。

  1. 组合模式的定义与特点
    组合(Composite Pattern)模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。

组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点,树形结构图如下。
在这里插入图片描述

由上图可以看出,==其实根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用;而叶子节点与树枝节点在语义上不属于用一种类型。==但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让它们具备一致行为。

这样,在组合模式中,整个树形结构中的对象都属于同一种类型,带来的好处就是用户不需要辨别是树枝节点还是叶子节点,可以直接进行操作,给用户的使用带来极大的便利。

  1. 模式的结构
    组合模式包含以下主要角色。
  • 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除)
  • 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。
  • 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

组合模式分为透明式的组合模式和安全式的组合模式。

(1) 透明方式

在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。其结构图如图 1 所示。
在这里插入图片描述图1 透明式的组合模式的结构图

(2) 安全方式
在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。其结构图如图 2 所示。
在这里插入图片描述

图2 安全式的组合模式的结构图

题外话:

学习是一个不断进步的过程,作为程序员就需要有不断进取的决心,你不能一直守着老本行,这样对你来说是不思进取,可能随着年龄增长,你的学习能力会下降,但是你还是可以学进去一点新东西的,可能会有人反驳我,我表示理解。这个新时代突出的就是一个卷字,但是我们却没办法,如果你不去卷,你就会被时代淘汰,没办法,要学会主动去释怀。如果自己真的跟不上时代了,那个时候就该想想后路了,主动退出也是一种明智的选择,高不成低不就的人生,其实我们每个人都在经历,有的时候想不开了,不放尝试一下放弃,坚持就是胜利有时候不一定是对,望理性对待…。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Matplotlib---雷达图

1. 雷达图 fig plt.figure(figsize(6, 6))x np. linspace(0, 2*np.pi, 6, endpointFalse) y [83, 61, 95, 67, 76, 88]# 保证首位相连 x np.concatenate((x, [x[0]])) y np.concatenate((y, [y[0]]))# 雷达图 axes plt.subplot(111, polarTrue) axes.plot(x, y, o-, l…

第十六届CISCN复现MISC——国粹

国粹 不是我说&#xff0c;我当时比赛的时候&#xff0c;在那里叭叭叭的数的老用心了结果他是一道非常不常规的图片密码题&#xff0c;又是一种我没见过的题型 看了一些大佬的解题&#xff0c;知道他是一个坐标类型的图片拼凑 发现很多都提到了opencv&#xff0c;又是一个知识…

考研算法32天:桶排 【桶排序】

算法介绍 桶排 举个例子&#xff0c;一个数组中的数是&#xff1a;4 1 2 3 5&#xff0c; 然后桶排的顺序是&#xff1a;将每个数应该在的下标算出来&#xff0c;咋算呢&#xff1f;这我们就得考虑两种情况&#xff1a;假设我们设现在这个需要找到自己在数组里位置的数是x。…

【计算机网络】IP 地址处理函数

目录 1.struct sockaddr_in的结构 2.一般我们写的结构 3.常见的“点分十进制” 到 ” uint32_t 的转化接口 3.1. inet_aton 和 inet_ntoa &#xff08;ipv4&#xff09; 3.2. inet_pton 和 inet_ntop (ipv4 和 ipv6&#xff09; 3.3. inet_addr 和 inet_network 3…

哈工大计算机网络课程传输层协议之:拥塞控制原理剖析

哈工大计算机网络课程传输层协议之&#xff1a;拥塞控制原理剖析 哈工大计算机网络课程传输层协议详解之&#xff1a;可靠数据传输的基本原理 哈工大计算机网络课程传输层协议详解之&#xff1a;流水线机制与滑动窗口协议 哈工大计算机网络课程传输层协议详解之&#xff1a;T…

【裸机开发】EPIT 定时器 —— 按键消抖

实际工程中&#xff0c;不能直接通过延时来消抖 ! 这里我们采用定时器来消抖&#xff0c;这也是内核处理消抖的一种方式。 目录 一、基本原理 1、延时消抖的弊端 2、定时器消抖原理 二、按键消抖实现 1、按键中断 2、定时器中断 三、附加&#xff1a;按键 / 定时器中断初…

Qgis加载在线XYZ瓦片影像服务的实践操作

目录 背景 一、XYZ瓦片相关知识 1、xyz瓦片金字塔 2、 瓦片编号 3、瓦片访问 二、在Qgis中加载在线地图 1、Qgis版本 2、瓦片加载 3、地图属性预览 总结 背景 在做电子地图应用的时候&#xff0c;很常见的会提到瓦片&#xff08;tile&#xff09;的概念&#xff0c;瓦片…

【MySQL】MVCC是如何解决快照读下的幻读问题的

文章目录 LBCC当前读 MVCC隐藏列undo logRead View 总结 我们从上文中了解到InnoDB默认的事务隔离级别是repeatable read&#xff08;后文中用简称RR&#xff09;&#xff0c;它为了解决该隔离级别下的幻读的并发问题&#xff0c;提出了LBCC和MVCC两种方案。其中LBCC解决的是当…

信号链噪声分析11

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 如今的射频(RF)系统变得越来越复杂。高度的复杂性要求所有系统指标&#xff08;例如严格的 链接和噪声预算&#xff09;达到最佳性能。确保整个信号链的正确设计至关重要。而信…

如何了解(海外抖音TiKToK)与国内抖音的区别以及介绍

一、海外抖音TK平台的优势 自从抖音在中国大受欢迎后&#xff0c;海外也推出了海外版抖音TK平台。尽管两者都是视频分享平台&#xff0c;但它们在一些方面具有明显的区别和独特的优势。下面将详细介绍海外抖音TK平台的优势以及与国内抖音的区别性。 优势&#xff1a; 1. 多元…

三防工业平板在哪些行业中得到广泛应用?

随着科技的不断进步&#xff0c;工业平板正逐渐成为各行业中不可或缺的工具。其中&#xff0c;三防工业平板由于其卓越的耐用性和丰富的功能&#xff0c;在许多行业中得到了广泛的应用。本文将重点介绍三防工业平板在以下几个行业中的应用。 三防工业平板在物流行业中发挥着关键…

vue-router.esm.js:2248 Error: Cannot find module ‘@/views/dylife/ 报错解决

具体是展示 一直加载 控制台报找不到模块 webpack版本问题&#xff0c;webpack4 不支持变量方式的动态 import &#xff0c;新版本需要使用 require() 来解决此问题。 return () > import(/views/${view}) 改写成 return (resolve) > require([/views/${view}], reso…

【三层交换机】网络杂谈(16)之三层交换机技术

涉及知识点 什么是三层交换机&#xff0c;三层交换技术的由来&#xff0c;三层交换机&#xff0c;三层交换的应用范例。深入了解三层交换机技术。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更多内容可去其主页关注下哈&#xff0c;不胜感激 文章目录 涉及知…

HBase(5):导入测试数据集

1 需求 将ORDER_INFO.txt 中的HBase数据集&#xff0c;我们需要将这些指令放到HBase中执行&#xff0c;将数据导入到HBase中。 可以看到这些都是一堆的put语句。那么如何才能将这些语句全部执行呢&#xff1f; 2 执行command文件 2.1 上传command文件 将该数据集文件上传到指…

6.5 指令与文件的搜寻

6.5.1 指令文件名的搜寻 在终端机模式当中&#xff0c;连续输入两次[tab]按键就能够知道使用者有多少指令可以下达。 which &#xff08;寻找“可执行文件”&#xff09; 这个指令是根据“PATH”这个环境变量所规范的路径&#xff0c;去搜寻“可执行文件”的文件名。所以&…

DETR系列:RT-DETR(一) 论文解析

论文&#xff1a;《DETRs Beat YOLOs on Real-time Object Detection》 2023.4 DETRs Beat YOLOs on Real-time Object Detection&#xff1a;https://arxiv.org/pdf/2304.08069.pdf 源码地址&#xff1a;https://github.com/PaddlePaddle/PaddleDetection/tree/develop/conf…

【Visual Studio】报错 ASSERT: “i >= 0 i < size()“,使用 C++ 语言,配合 Qt 开发串口通信界面

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 这个 Bug 是我做这个工程时遇到的&#xff1a;【Visual Studio】Qt 的实时绘图曲线功能&#xff0c;使用 C 语言&#xff0c;配合 Qt 开发串口通信界面。 文…

javaweb学习2

p标签使用 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!--p标签定义段落 p元素自动在其前后创建一段空白--> hello&#xff0c;world &l…

设计模式之访问者模式笔记

设计模式之访问者模式笔记 说明Iterator(访问者)目录访问者模式示例类图抽象访问者角色类抽象元素角色类宠物猫类宠物狗类自己类其他人类家类测试类 说明 记录下学习设计模式-访问者模式的写法。JDK使用版本为1.8版本。 Iterator(访问者) 意图:表示一个作用于某对象结构中的…

日历组件 el-calendar 实现标记功能

需求&#xff1a;在日历组件中选择月份时&#xff0c;可以显示当月已经质检或需质检的数据 思路&#xff1a;前端每次点击日期选择器的时候调用接口&#xff0c;接口返回当月需要质检或已质检的数据&#xff0c;前端拿到数据就开始做判断然后回显。 大体样式 代码&#xff1a…