设计模式 8 组合模式

news/2024/9/15 17:02:21/ 标签: 设计模式, 组合模式

设计模式 8

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • 设计模式 8
    • 组合模式(Composite Pattern)
      • 1 定义
      • 2 结构
      • 3 示例代码
      • 4 特点
      • 5 适用场景
      • 6 与其他模式对比

组合模式(Composite Pattern)

1 定义

组合模式通过定义树形结构来组成对象,使得客户端对单个对象和对象集合的处理方式一致。这个模式让你可以使用相同的接口来操作单一对象和对象集合,简化了代码和操作逻辑。

2 结构

组合模式的结构包含以下角色:

  • 组件(Component): 定义树形结构中所有对象的共同接口,包括叶子节点和复合节点(容器节点)。
  • 叶子节点(Leaf): 叶子节点是树的基本元素,它实现了 Component 接口,但没有子节点。
  • 复合节点(Composite): 复合节点可以包含子节点,包括叶子节点和其他复合节点,实现了 Component 接口并能够管理其子节点。

UML 类图

+---------------------+
|     Component       |
+---------------------+
| + Operation()       |
+---------------------+
| + Add(Component)    |
| + Remove(Component) |
| + GetChild(int)     |
+---------------------+^|
+---------------------+       +---------------------+
|      Leaf           |       |     Composite       |
+---------------------+       +---------------------+
| + Operation()       |       | + Operation()       |
+---------------------+       +---------------------+| + Add(Component)    || + Remove(Component) || + GetChild(int)     |+---------------------+

3 示例代码

以下是一个实现组合模式的简单示例。在这个示例中,我们有一个文件系统,其中 File 是叶子节点,Directory 是复合节点(目录),它可以包含多个文件或目录。

组件接口

// 组件接口
public abstract class FileSystemComponent
{public abstract void Display(int depth);// 组合节点的方法public virtual void Add(FileSystemComponent component) { }public virtual void Remove(FileSystemComponent component) { }public virtual FileSystemComponent GetChild(int index) { return null; }
}

叶子节点类

// 叶子节点类:文件
public class File : FileSystemComponent
{private string _name;public File(string name){_name = name;}public override void Display(int depth){Console.WriteLine(new string('-', depth) + _name);}
}

复合节点类

// 复合节点类:目录
public class Directory : FileSystemComponent
{private List<FileSystemComponent> _children = new List<FileSystemComponent>();private string _name;public Directory(string name){_name = name;}public override void Add(FileSystemComponent component){_children.Add(component);}public override void Remove(FileSystemComponent component){_children.Remove(component);}public override FileSystemComponent GetChild(int index){return _children[index];}public override void Display(int depth){Console.WriteLine(new string('-', depth) + _name);foreach (var child in _children){child.Display(depth + 2);}}
}

客户端代码

class Program
{static void Main(string[] args){// 创建文件和目录FileSystemComponent file1 = new File("File 1");FileSystemComponent file2 = new File("File 2");FileSystemComponent file3 = new File("File 3");Directory directory1 = new Directory("Directory 1");Directory directory2 = new Directory("Directory 2");// 构建目录树directory1.Add(file1);directory1.Add(file2);directory2.Add(file3);directory2.Add(directory1);// 显示目录树directory2.Display(1);}
}

在这个示例中:

  • FileSystemComponent 是组件接口,定义了叶子节点和复合节点的共同接口。
  • File 是叶子节点,表示文件,没有子节点。
  • Directory 是复合节点,表示目录,可以包含多个子节点(文件或其他目录)。

4 特点

  • 优点:

    • 简化客户端代码: 客户端代码可以统一处理叶子节点和复合节点,减少了代码复杂度。

    • 增加灵活性: 通过将叶子节点和复合节点统一成一个接口,可以灵活地构建和管理复杂的树形结构。

    • 符合开闭原则: 可以通过添加新的叶子节点或复合节点来扩展功能,而无需修改现有代码。

  • 缺点:

    • 设计复杂: 组合模式可能会增加系统的复杂性,因为你需要设计和管理树形结构。

    • 性能问题: 如果树形结构非常庞大,操作树形结构可能会影响性能。

5 适用场景

  • 部分-整体层次结构: 当你需要表示部分-整体的层次结构时,例如文件系统、组织结构等。
  • 统一处理树形结构: 当你需要统一处理树形结构中的对象,无论它们是叶子节点还是复合节点。
  • 动态构建树形结构: 当你需要动态构建和操作复杂的树形结构时,例如图形界面中的组件树。

6 与其他模式对比

  • 与桥接模式的区别: 组合模式用于表示部分-整体层次结构,而桥接模式用于将抽象与实现分离。
  • 与装饰器模式的区别: 组合模式主要用于处理树形结构,而装饰器模式用于动态地增加对象的功能。

组合模式非常适合用来构建复杂的树形结构,通过将对象和对象集合统一成一个接口,它能够简化对复杂结构的操作,并提高系统的灵活性和可扩展性。


http://www.ppmy.cn/news/1519897.html

相关文章

golang 于 goland 无法运行

命令行 go build -o main.go 等等 报出 # command-line-arguments runtime.main_mainf: function main is undeclared in the main package 直接goland运行 爆出 command-line-arguements 等等 goland中直接删除配置( Edit Configurations )&#xff0c;或者把运行模式从 Fil…

redis主从+高可用切换+负载均衡

1. redis主从配置 # 在master中 cp sentinel.conf /etc/redis/ vim /etc/redis/sentinel.conf scp /etc/redis/sentinel.conf server2:/etc/redis/ scp /etc/redis/sentinel.conf server3:/etc/redis/ redis-sentinel /etc/redis/sentinel.conf # 启动监控# 在slave中 redis-s…

第十三节:学习Springboot整合mybatis——完整篇(自学Spring boot 3.x的第三天)

大家好&#xff0c;今天记录下学习springboot的第三天。​网创有方 这节详细记录了如何使用springboot整合mybatis方法&#xff0c;并成功实现将请求信息插入本地的mysql数据库。 由于只是为了方便本地验证&#xff0c;实际项目是需要部署到服务器上去的&#xff0c;所以就采用…

“NoSQL数据库技术及其应用”写作框架,软考高级,系统架构设计师

论文真题 随着互联网web2.0网站的兴起&#xff0c;传统关系数据库在应对web2.0 网站&#xff0c;特别是超大规模和高并发的web2.0纯动态SNS网站上已经显得力不从心&#xff0c;暴露了很多难以克服的问题&#xff0c;而非关系型的数据库则由于其本身的特点得到了非常迅速的发展…

汽车免拆诊断案例 | 2012 款大众速腾车发动机偶尔抖动

故障现象 一辆2012款大众速腾车&#xff0c;搭载CST发动机和干式双离合变速器&#xff0c;累计行驶里程约为17万km。车主反映&#xff0c;发动机偶尔抖动。 故障诊断 接车后试车&#xff0c;确认发动机怠速偶尔抖动&#xff0c;且在D挡起步时抖动明显。用故障检测仪检测&…

仿论坛项目--开发社区首页

• 开发流程 1次请求的执行过程 • 分步实现开发社区首页&#xff0c;显示前10个帖子开发分页组件&#xff0c;分页显示所有的帖子 项目调试技巧 • 响应状态码的含义 • 服务端断点调试技巧 • 客户端断点调试技巧 • 设置日志级别&#xff0c;并将日志输出到不同的终端 h…

刷题记录(2)

1. HWOD机试 - 模拟消息队列(100) package com.yue.test;import org.junit.Test;import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List;/*** Author: 夜雨* Date: 2021-12-08-10:31* Description:* Version 1.0*/ public…

SAPUI5基础知识25 - 聚合绑定(Aggregation Binding)

1. 背景 Aggregation Binding 是 SAPUI5 中的一种数据绑定方式&#xff0c;用于将数据模型中的集合&#xff08;如数组&#xff09;绑定到 UI 控件的聚合&#xff08;如列表项、表格行等&#xff09;。 常见的场景包括将一个数组绑定到 sap.m.List 的 items 聚合&#xff0c;…

如何定义核心场景用例?

​首先我们解决两个问题&#xff1a; 1.什么是场景测试&#xff1f; 2.什么是核心场景&#xff1f; 1、什么是场景测试&#xff1f; &#x1f3af; 1.1&#xff1a;什么是场景 事件触发时的情景形成了场景。场景必不可少的几个要素&#xff1a;环境、人、时间、行为。简而…

JavaWeb——介绍(什么是Web、Web网站的开发模式)、初始Web前端(Web标准、学习内容)

目录 介绍 什么是Web Web网站的开发模式 初识Web前端 Web标准 学习内容 介绍 JavaWeb学习路线 &#xff08;仅用作参考&#xff09; 什么是Web Web&#xff1a;全球广域网&#xff0c;也称为万维网&#xff08;www World Wide Web)&#xff0c;能够通过浏览器访问的…

揭秘面试官常见问题 —— JavaScript 闭包

1. 什么是闭包&#xff1f; 闭包是 JavaScript 中的一种特性&#xff0c;它允许一个函数在定义的环境之外仍然能够访问和操作定义时的作用域中的变量。换句话说&#xff0c;闭包是指函数可以“记住”并访问它被创建时所处的词法作用域。 简单来说&#xff1a; - 当一个函数被…

[Meachines] [Medium] SecNotes XSRF跨站请求伪造+SMB-Webshell上传+Linux子系统命令历史记录泄露权限提升

信息收集 IP AddressOpening Ports10.10.10.97TCP:80&#xff0c;445&#xff0c;8808 $ nmap -p- 10.10.10.97 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 | http-title: Secure Notes - Login |…

SpringBoot中基于MongoDB的findAndModify原子操作实现分布式锁原理详解

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

网络是怎样连接的

网络是怎样连接的 HTTPDNS数据通信协议栈——TCP/IPRJ-45接口信号衰减噪声干扰双绞线MDI接口集线器交换机路由器接入网ADSL接入网FTTH接入网用户认证和配置下发DHCPPOPWeb服务器的部署地点防火墙 HTTP HTTP发展史&#xff1a; 1991 – HTTP/0.91996 – HTTP/1.01997 – HTTP/…

人工智能领域面试基础问题整理(二):什么是人工智能?

当你说你的专业是“人工智能”时&#xff0c;面试官问你&#xff1a;“假如我是一个不懂AI的人&#xff0c;你能和我说说&#xff0c;什么是AI吗&#xff1f;”你会怎么回答。 我们可以从以下几个方面入手&#xff1a; 1、人工智能的定义 人工智能&#xff08;Artificial Inte…

Android Studio gradle下载太慢了!怎么办?(已解决)

Android Studio&#xff01;你到底干了什么&#xff1f;&#xff01; 不能高速下载gradle&#xff0c;我等如何进行app编程&#xff1f;&#xff01; 很简单&#xff0c;我修改gradle地址不就是了。 找到gradle-wrapper.properties文件 修改其中distributionUrl的地址。 将 ht…

[Leetcode 51][Hard]-n皇后问题-回溯

目录 一、题目描述 二、整体思路 三、代码 一、题目描述 原题地址 二、整体思路 这种可以算是组合问题的变种&#xff0c;在回溯函数中我们要保存当前已放置皇后的所有位置&#xff0c;同时递归调用时要进行寻找下一个皇后的放置位置。那么我们可以逐行遍历棋盘并作为递归调…

如何完美实现 Go 服务的平滑升级

Go 服务作为常驻进程,如何进行服务升级呢?你可能会觉得这还不简单,先将现有服务停止,再启动新的服务不就可以了。可是将现有服务停止时,如果它还在处理请求,那么这些请求该如何处理?另外,在现有服务已经退出但是新服务还没有启动期间,新的请求到达了又该如何处理? Go…

Logistic分类算法原理及Python实践

一、Logistic分类算法原理 Logistic分类算法&#xff0c;也称为逻辑回归&#xff08;Logistic Regression&#xff09;&#xff0c;是机器学习中的一种经典分类算法&#xff0c;主要用于解决二分类问题。其原理基于线性回归和逻辑函数&#xff08;Sigmoid函数&#xff09;的组…

3.4 数据传送指令

&#x1f393; 微机原理考点专栏&#xff08;通篇免费&#xff09; 欢迎来到我的微机原理专栏&#xff01;我将帮助你在最短时间内掌握微机原理的核心内容&#xff0c;为你的考研或期末考试保驾护航。 为什么选择我的视频&#xff1f; 全程考点讲解&#xff1a;每一节视频都…