设计模式之复合模式

news2024/9/23 6:38:25

组合模式(Composite Pattern),又称为“整体-部分”(Part-Whole)模式,是一种结构型设计模式。其核心思想是将对象组合成树形结构以表示“部分-整体”的层次关系,使得用户对单个对象和组合对象的使用具有一致性。在组合模式中,客户将单个对象和组合对象同等看待,无需关心自己正在处理的是单个对象还是组合对象。

一、组合模式的角色组成

组合模式通常包含以下几个主要角色:

1、抽象构件(Component)

定义了一个对象的接口,用于访问和管理组件的子对象。可以是接口或抽象类,声明了对象共有的方法,包括用于访问和管理子构件的方法(如增加子构件、删除子构件、获取子构件等)。在透明式组合模式中,还声明了所有子类中的全部方法。

2、树叶构件(Leaf)

在组合中表示叶子节点对象,是组合中的叶节点对象,没有子节点。实现了抽象构件中定义的行为,但对于那些访问及管理子构件的方法,可以通过异常等方式进行处理。

3、容器构件(Composite)/树枝构件(Composite)

在组合中表示容器节点对象,是组合中的分支节点对象,包含子节点。其子节点可以是叶子节点,也可以是容器节点。提供一个集合用于存储子节点,并实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法。

二、组合模式的实现方式

组合模式的实现根据所实现接口的区别分为两种形式,分别称为安全式组合模式和透明式组合模式。

1、安全式组合模式

管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件类中。抽象构件不定义出管理子对象的方法,这一定义由树枝构件对象给出。缺点是不够透明,因为树叶类和树枝类将具有不同的接口。

2、透明式组合模式

要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定接口。客户端可以一致地处理所有的对象,无须区分是叶子节点还是容器节点。缺点是树叶构件本来没有管理子对象的方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。

三、组合模式的应用场景

组合模式适用于需要表示对象的部分-整体层次结构的场景,如:

1、文件系统中的文件和文件夹

2、窗体程序中的简单控件与容器控件

3、图形界面中的菜单项、按钮和其他控件的树形结构

4、表示公司或组织的部门结构

5、XML文档的层次结构解析等

四、代码示例-Java

下面是一个使用透明式组合模式的Java代码示例,用于模拟公司组织架构中的部门及员工统计。

1. 定义抽象构件(Component)

首先,定义一个抽象构件类Department,表示公司部门或员工,包含基本的属性和方法。

abstract class Department {  
    protected String name;  
      
    public Department(String name) {  
        this.name = name;  
    }  
      
    // 定义一个抽象方法,用于统计人数,实际实现由子类完成  
    public abstract int getCount();  
      
    // 添加子部门或员工(在透明组合模式中,所有类都应包含此方法)  
    public void add(Department department) {  
        throw new UnsupportedOperationException("This is a leaf.");  
    }  
      
    // 删除子部门或员工(同样,所有类都应包含此方法)  
    public void remove(Department department) {  
        throw new UnsupportedOperationException("This is a leaf.");  
    }  
      
    // 显示部门或员工信息  
    public void display(int depth) {  
        StringBuilder indent = new StringBuilder();  
        for (int i = 0; i < depth; i++) {  
            indent.append("--");  
        }  
        System.out.println(indent + name + " (人数: " + getCount() + ")");  
    }  
}

2. 实现树叶构件(Leaf)

定义一个员工类Employee,继承自Department,但只包含员工的基本信息,不实现添加和删除子对象的方法。

class Employee extends Department {  
    private int count = 1; // 员工人数默认为1  
      
    public Employee(String name) {  
        super(name);  
    }  
      
    @Override  
    public int getCount() {  
        return count; // 员工人数始终为1  
    }  
      
    // Employee不需要添加或删除子对象的方法,因此不重写add和remove  
}

3. 实现容器构件(Composite)

定义一个部门类Dept,继承自Department,并实现添加、删除子对象和统计人数的功能。

import java.util.ArrayList;  
import java.util.List;  
  
class Dept extends Department {  
    private List<Department> children = new ArrayList<>();  
      
    public Dept(String name) {  
        super(name);  
    }  
      
    @Override  
    public void add(Department department) {  
        children.add(department);  
    }  
      
    @Override  
    public void remove(Department department) {  
        children.remove(department);  
    }  
      
    @Override  
    public int getCount() {  
        int count = 0;  
        for (Department child : children) {  
            count += child.getCount();  
        }  
        return count;  
    }  
      
    @Override  
    public void display(int depth) {  
        super.display(depth);  
        for (Department child : children) {  
            child.display(depth + 1);  
        }  
    }  
}

4. 客户端代码

最后,编写客户端代码来构建公司组织架构并统计总人数。

public class CompanyStructureDemo {  
    public static void main(String[] args) {  
        // 创建部门及员工  
        Dept root = new Dept("总公司");  
        Dept itDept = new Dept("IT部");  
        Dept hrDept = new Dept("人事部");  
        Employee itEmployee1 = new Employee("张三");  
        Employee itEmployee2 = new Employee("李四");  
        Employee hrEmployee1 = new Employee("王五");  
          
        // 构建组织架构  
        root.add(itDept);  
        root.add(hrDept);  
        itDept.add(itEmployee1);  
        itDept.add(itEmployee2);  
        hrDept.add(hrEmployee1);  
          
        // 显示组织架构及统计人数  
        root.display(0);  
        System.out.println("公司总人数: " + root.getCount());  
    }  
}

五、组合模式的优缺点

1、优点

简化客户端代码:客户端可以一致地处理单个对象和组合对象,无需关心自己处理的是单个对象还是组合对象。
高扩展性:更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”。

2、缺点

设计较复杂:客户端需要花更多时间理清类之间的层次关系。
性能问题:由于组合模式中的对象可能被存储在多个地方,可能导致性能问题,特别是在树形结构复杂的情况下。

六、总结

组合模式通过将对象组合成树形结构来表示“部分-整体”的层次关系,简化了客户端代码,提高了系统的扩展性和灵活性。然而,它也存在设计复杂和潜在的性能问题。在实际应用中,应根据具体场景和需求来选择合适的设计模式。

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

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

相关文章

2024PHP彩虹工具网源码一个多功能工具箱程序支持72种常用站长和开发等工具

安装&#xff1a; PHP>7.4 伪静态设置Thinkphp 设置/public为网站运行目录 访问你的域名/install进行安装即可 安装扩展 sg11 &#xff0c;fileinfo &#xff0c; ionCube 常用功能 站长工具&#xff1a;ICP备案查询、IP地址查询、域名Whios查询、腾讯域名拦截查询、Mysql…

828华为云征文 | 构建高效搜索解决方案,Elasticsearch Kibana的完美结合

前言 构建高效搜索解决方案&#xff0c;FlexusX服务器与Elasticsearch & Kibana的完美结合&#xff0c;为企业带来云端搜索新体验。FlexusX实例以其卓越性能与灵活扩展性&#xff0c;确保高并发搜索的流畅运行。部署Elasticsearch&#xff0c;享受分布式搜索的精准与快速&a…

从Yargs源码学习中间件的设计

yargs中间件介绍 yargs 是一个用于解析命令行参数的流行库&#xff0c;它能帮助开发者轻松地定义 CLI&#xff08;命令行接口&#xff09;&#xff0c;并提供参数处理、命令组织、help文本自动生成等功能。今天我们来学习一下它对中间件的支持。 中间件的API详细信息&#xff0…

Python | Leetcode Python题解之第430题扁平化多级双向链表

题目&#xff1a; 题解&#xff1a; class Solution:def flatten(self, head: "Node") -> "Node":def dfs(node: "Node") -> "Node":cur node# 记录链表的最后一个节点last Nonewhile cur:nxt cur.next# 如果有子节点&#…

旋转机械故障数据集 全网首发

旋转机械故障 数据集 11G资料 泵、齿轮箱、电机、流量、液压系统、轴承(西储大学、辛辛那提大学、FEMTO、MOSFET)、PHM08挑战数据集、我闪发动机降级模拟数据集、铣床等 旋转机械故障数据集 数据集描述 该数据集是一个综合性的旋转机械故障检测和诊断数据集&#xff0c;旨在…

【ChatGPT】提示词助力广告文案、PPT制作与书籍推荐的高效新模式

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;高效广告推销文案提示词使用方法 &#x1f4af;AI自动生成PPT全流程提示词使用方法 &#x1f4af;精选书籍推荐爆款文案提示词使用方法 &#x1f4af;小结 &#x1f4af;…

【VUE3.0】动手做一套像素风的前端UI组件库---Radio

目录 引言做之前先仔细看看UI设计稿解读一下都有哪些元素&#xff1a;参考下成熟的组件库&#xff0c;看看还需要做什么&#xff1f; 代码编写1. 设计group包裹选项的组件group.vueitem.vue 2. 让group的v-model和item的value联动起来3. 完善一下item的指示器样式4. 补充禁用模…

【测试】——JUnit

&#x1f4d6; 前言&#xff1a;JUnit 是一个流行的 Java 测试框架&#xff0c;主要用于编写和运行单元测试&#xff0c;用来管理测试用例。本文采用JUnit 5 目录 &#x1f552; 1. 添加依赖&#x1f552; 2. 注解&#x1f558; 2.1 Test&#x1f558; 2.2 BeforeAll AfterAll&…

【Docker】基于docker compose部署artifactory-cpp-ce服务

基于docker compose部署artifactory-cpp-ce服务 1 环境准备2 必要文件创建与编写3 拉取镜像-创建容器并后台运行4 访问JFog Artifactory 服务 1 环境准备 docker 以及其插件docker compose &#xff0c;我使用的版本如下图所示&#xff1a; postgresql 的jdbc驱动, 我使用的是…

【图像检索】基于纹理(LBP)和形状特征的图像检索,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于纹理(LBP)和形状特征&#xff08;hu特征&#xff09;的图像检索&#xff0c;用m…

力扣206.反转链表

力扣《反转链表》系列文章目录 刷题次序&#xff0c;由易到难&#xff0c;一次刷通&#xff01;&#xff01;&#xff01; 题目题解206. 反转链表反转链表的全部 题解192. 反转链表 II反转链表的指定段 题解224. 两两交换链表中的节点两个一组反转链表 题解325. K 个一组翻转…

【二等奖论文】2024年华为杯研究生数学建模E题成品论文获取入口

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片链接&#xff0c;那是获取资料的入口&#xff01; 点击链接获取【2024华为杯研赛资料汇总】&#xff1a; https://qm.qq.com/q/Wgk64ntZCihttps://qm.qq.com/q/Wgk64ntZCi 详细建模思路&#xff1a; 要解…

C++--模板(template)详解—— 函数模板与类模板

目录 1.泛型编程 2.函数模板 2.1 函数模板概念 2.2 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3.类模板 3.1 类模板的定义格式 3.2 类模板的实例化 1.泛型编程 在C中如果让你写一个交换函数&#xff0c;应该怎么做呢&#xff1f…

二叉树进阶【c++实现】【二叉搜索树的实现】

目录 二叉树进阶1.二叉搜索树1.1二叉搜索树的实现1.1.1二叉搜索树的查找1.1.2二叉搜索树的插入1.1.3中序遍历(排序)1.1.4二叉搜索树的删除(重点) 1.2二叉搜索树的应用1.2.1K模型1.2.2KV模型 1.3二叉搜索树的性能分析 二叉树进阶 前言&#xff1a; map和set特性需要先铺垫二叉搜…

Python3网络爬虫开发实战(16)分布式爬虫(第一版)

文章目录 一、分布式爬虫原理1.1 分布式爬虫架构1.2 维护爬取队列1.3 怎样来去重1.4 防止中断1.5 架构实现 二、Scrapy-Redis 源码解析2.1 获取源码2.2 爬取队列2.3 去重过滤2.4 调度器 三、Scrapy 分布式实现3.1 准备工作3.2 搭建 Redis 服务器3.3 部署代理池和 Cookies 池3.4…

超越sora,最新文生视频CogVideoX-5b模型分享

CogVideoX-5B是由智谱 AI 开源的一款先进的文本到视频生成模型&#xff0c;它是 CogVideoX 系列中的更大尺寸版本&#xff0c;旨在提供更高质量的视频生成效果。 CogVideoX-5B 采用了 3D 因果变分自编码器&#xff08;3D causal VAE&#xff09;技术&#xff0c;通过在空间和时…

【OpenAI o1背后技术】Sef-play RL:LLM通过博弈实现进化

【OpenAI o1背后技术】Sef-play RL&#xff1a;LLM通过博弈实现进化 OpenAI o1是经过强化学习训练来执行复杂推理任务的新型语言模型。特点就是&#xff0c;o1在回答之前会思考——它可以在响应用户之前产生一个很长的内部思维链。也就是该模型在作出反应之前&#xff0c;需要…

简单题104. 二叉树的最大深度 (python)20240922

问题描述&#xff1a; python&#xff1a; # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution(object…

Python 入门(一、使用 VSCode 开发 Python 环境搭建)

Python 入门第一课 &#xff0c;环境搭建...... by 矜辰所致前言 现在不会 Python &#xff0c;好像不那么合适&#xff0c;咱先不求精通&#xff0c;但也不能不会&#xff0c;话不多说&#xff0c;开干&#xff01; 这是 Python 入门第一课&#xff0c;当然是做好准备工作&a…

论前端框架的对比和选择 依据 前端框架的误区

前端框架的对比和选择依据 在前端开发中&#xff0c;有多种框架可供选择&#xff0c;以下是一些常见前端框架的对比和选择依据&#xff1a; 一、Vue.js 特点&#xff1a; 渐进式框架&#xff0c;灵活度高&#xff0c;可以逐步引入到项目中。学习曲线相对较平缓&#xff0c;容…