探索设计模式:组合模式

news2024/9/9 8:02:28

探索设计模式:组合模式

    • 🧐1. 概念
    • 🎯2. 作用
    • 📦3. 用法
      • 📦3.1 绘图示例
      • 📦3.2 文件示例
    • 💻4. 使用场景

在这里插入图片描述

  在软件设计中,组合模式Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。这种设计模式使得客户端可以以一致的方式处理单个对象和组合对象,极大地提升了代码的灵活性和可维护性。

🧐1. 概念


组合模式由如下三个主要角色组成:

  1. Component(组件):这是一个接口或抽象类,定义了所有对象(包括叶子和容器)的通用行为。
  2. Leaf(叶子):代表树的叶节点,叶节点没有子节点。它实现了Component接口。
  3. Composite(容器):这是一个包含子节点的节点,子节点可以是叶子节点或其他容器节点。它也实现了 Component 接口,并允许对子节点进行操作,如添加、删除等。

🎯2. 作用


组合模式的主要作用:

  • 统一接口:简单对象和复合对象都实现相同的接口,客户端无需关心它处理的是单个对象还是一个组合对象。
  • 降低复杂性:通过树形结构的管理和操作,简化了对复杂对象图(Object graph)的操作。,
  • 增强灵活性:可以在运行时方便地增删组合内部的成员。

📦3. 用法


在这里插入图片描述

📦3.1 绘图示例

  我们通过一个实际的代码示例来展示组合模式的用法。假设我们在开发一个绘图的应用程序,可以绘制不同类型的图形(如线条、圆形),并且可以将图形组合成复杂图形。

// Component: 定义了图形的公共操作
interface Graphic {
    void draw();
}

// Leaf: 具体的图形实现(如线条)
class Line implements Graphic {
    @Override
    public void draw() {
        System.out.println("Drawing a line");
    }
}

// Leaf: 具体的图形实现(如圆形)
class Circle implements Graphic {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

// Composite: 可以包含多个图形对象
class CompositeGraphic implements Graphic {
    private final List<Graphic> childGraphics = new ArrayList<>();

    public void add(Graphic graphic) {
        childGraphics.add(graphic);
    }

    public void remove(Graphic graphic) {
        childGraphics.remove(graphic);
    }

    @Override
    public void draw() {
        for (Graphic graphic : childGraphics) {
            graphic.draw();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建叶子节点
        Graphic line1 = new Line();
        Graphic circle1 = new Circle();

        // 创建组合对象
        CompositeGraphic compositeGraphic = new CompositeGraphic();
        compositeGraphic.add(line1);
        compositeGraphic.add(circle1);

        // 绘制所有图形
        compositeGraphic.draw();
    }
}

  在这个示例中,CompositeGraphic 类可以包含多个 Graphic 对象(即具体的图形如线条和圆形),并且可以像单个 Graphic 对象一样执行 draw 操作。这大大简化了客户端代码,使得客户端可以专注于“绘制”动作,而无需关心底层的实现细节。

📦3.2 文件示例

以下是具体的代码实现,展示了一个简单的文件系统结构,其中包含文件和目录。

// 组件接口:FileSystemComponent
public interface FileSystemComponent {
    void showDetails();  // 显示组件的详细信息
    String getName();    // 获取组件名称
    int getSize();       // 获取组件大小
}

// 叶子对象:File
public class File implements FileSystemComponent {
    private String name;
    private int size; // 文件大小,以KB为单位

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public void showDetails() {
        System.out.println("File: " + name + " (Size: " + size + "KB)");
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getSize() {
        return size;
    }
}

// 组合对象:Directory
public class Directory implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> components = new ArrayList<>();

    public Directory(String name) {
        this.name = name;
    }

    public void addComponent(FileSystemComponent component) {
        components.add(component);
    }

    public void removeComponent(FileSystemComponent component) {
        components.remove(component);
    }

    @Override
    public void showDetails() {
        System.out.println("Directory: " + name);
        for (FileSystemComponent component : components) {
            component.showDetails();
        }
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getSize() {
        int totalSize = 0;
        for (FileSystemComponent component : components) {
            totalSize += component.getSize();
        }
        return totalSize;
    }

    public FileSystemComponent findComponentByName(String componentName) {
        if (name.equalsIgnoreCase(componentName)) {
            return this;
        }
        for (FileSystemComponent component : components) {
            if (component.getName().equalsIgnoreCase(componentName)) {
                return component;
            }
            if (component instanceof Directory) {
                FileSystemComponent found = ((Directory) component).findComponentByName(componentName);
                if (found != null) {
                    return found;
                }
            }
        }
        return null; // 找不到指定名称的组件
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        // 创建文件
        FileSystemComponent file1 = new File("file1.txt", 10);
        FileSystemComponent file2 = new File("file2.txt", 20);
        FileSystemComponent file3 = new File("file3.jpg", 50);
        FileSystemComponent file4 = new File("file4.mp4", 200);

        // 创建目录
        Directory directory1 = new Directory("Folder1");
        Directory directory2 = new Directory("Folder2");

        // 组合对象添加子组件
        directory1.addComponent(file1);
        directory1.addComponent(file2);

        directory2.addComponent(file3);
        directory2.addComponent(file4);
        directory2.addComponent(directory1); // 嵌套目录

        // 显示详细信息
        directory2.showDetails();  // 输出整个目录树的结构和内容
        System.out.println("Total size of " + directory2.getName() + ": " + directory2.getSize() + "KB");

        // 查找组件
        FileSystemComponent found = directory2.findComponentByName("file3.jpg");
        if (found != null) {
            System.out.println("Found component: " + found.getName() + " (Size: " + found.getSize() + "KB)");
        } else {
            System.out.println("Component not found");
        }
    }
}

💻4. 使用场景


  1. 图形界面库:在图形界面开发中,UI 元素(按钮、文本框等)和容器元素(面板、窗口等)可以使用组合模式来构建复杂的用户界面。这样,可以统一处理单个元素和组合元素,使得客户端代码更简洁。
  2. 文件系统和目录结构:文件系统是一个经典的组合模式应用场景。文件夹可以包含文件和其他文件夹,形成一个树形结构。通过组合模式,可以一致地处理文件和文件夹,而不必在客户端代码中区分它们。
  3. 组织架构和人员管理:在组织架构中,部门可以包含员工和其他部门,形成一个层次结构。通过组合模式,可以一致地管理单个员工和组合部门,简化组织管理的代码。
  4. 菜单和菜单项:菜单系统通常包含菜单项和子菜单,可以使用组合模式来构建菜单层次结构。这样,可以一致地处理单个菜单项和包含子菜单的菜单。

  一般来说,以下几个情况下可以考虑用组合模式

  • 当客户端需要统一处理单个对象和组合对象时,可以使用组合模式。
  • 当希望客户端忽略组合对象与单个对象的差异,统一使用相同的接口时,可以使用组合模式。
  • 当希望在不同层次结构中使用相同的处理方式,并且希望动态添加或删除对象时,可以使用组合模式。

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

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

相关文章

WebLogic:弱口令,木马反弹连接

weblogic WebLogic 是 Oracle 公司开发的应用服务器&#xff0c;主要用作开发、集成、部署和管理大型分布式 Web 应用、网络应用和数据库应用的 Java 应用服务器。它在历史上曾出现过多个安全漏洞&#xff0c;其中包括弱口令、任意文件上传、SSRF、反序列化漏洞等 常见版本&a…

YOLOv8入门 | yaml文件解读,YOLOv8网络结构打印以及网络结构图绘制【小白必看】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

软考高级-系统架构设计师

2024广东深圳考试时间 报考人员可登录中国计算机技术职业资格网&#xff08;http://www.ruankao.org.cn&#xff09;进行网上报名&#xff0c;报名前须扫码绑定个人微信&#xff0c;不允许代报名。 上半年考试报名信息填报时间&#xff1a;2024年3月25日9:00&#xff0d;4月2日…

【ASR系列】【论文阅读】CIF

1. 概念学习 WER(word error rate): 单词错误率,是评价asr系统的一种重要指标,越低越好 是Continuous integrate-and-fire的简称,集成和发射,翻译成积分不太合理,可理解为求和 2. 思想 一个人说了几句话,在说第一句话的时候会不断地对输入的信号集成,说完这句话(达…

计算机毕业设计PySpark+Django高考志愿填报推荐系统 高考预测 高考大数据分析 Hadoop Spark 机器学习 深度学习 Python

在撰写关于《PySpark高考推荐系统》的论文时&#xff0c;推荐算法的实现通常会利用PySpark&#xff0c;这是Apache Spark的Python API。以下是一个使用PySpark中MLlib库的ALS&#xff08;交替最小二乘法&#xff09;算法来构建高考推荐系统的示例代码。在这个示例中&#xff0c…

短视频矩阵系统搭建教程,源码获取,部署上线指南

目录 一、短视频矩阵是什么&#xff1f; 二、搭建教程 1、前端界面开发 2、后端架构搭建 3、第三方视频平台对接 三、部分代码展示 一、短视频矩阵是什么&#xff1f; 短视频矩阵系统是一种集成了多元短视频平台功能的综合性管理工具&#xff0c;它汇聚了多个视频发布渠…

MyBatis-Plus知识总结

1. MP前瞻 官网&#xff1a;https://baomidou.com/ 1、MyBatis-Plus是什么&#xff1a;MyBatis-Plus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;它在MyBatis的基础上只做增强不做改变&#xff0c;为简化开发、提供效率而生。并且MP内部提供了丰富的 AP…

(已解决,附RDM工具解决方案)如何实现多个redis连接间指定key(键)的数据同步

目录 问题现象&#xff1a; 问题分析&#xff1a; 方法一-重复执行操作&#xff1a; 方法二-redis命令实现导出再导入&#xff1a; 方法三-使用rdb文件实现数据迁移 方法四-RDM工具自带的数据复制功能 总结&#xff1a; 解决方法&#xff1a; 方法一-重复执行…

SpringMVC(包括Servlet,会话技术)理解

目录 前言&#xff1a; Servlet&#xff1a; http请求的内容&#xff1a; 会话技术&#xff1a; Cookie&#xff1a; Session&#xff1a; 案例实现代码&#xff1a; 小总结&#xff08;感想&#xff09;&#xff1a; SpringMVC介绍&#xff1a; 调用流程&#xff1a…

最后一个单词的长度-string

58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int lengthOfLastWord(string s) {int right s.size()-1;while(s[right] ){right--;}int cnt 0;while(right > 0 && s[right] ! ){right--;cnt;}return cnt;} }; 注意…

达梦数据库系列—39.统计信息详解

目录 达梦统计信息 举例 统计信息的缺点 统计信息管理 手动收集 自动收集 查看统计信息 更新统计信息 删除统计信息 达梦统计信息 达梦数据库的统计信息分为表统计信息&#xff0c;列统计信息&#xff0c;索引统计信息。 表&#xff1a;计算表的行数、所占的页数目、…

二百五十、Linux——visudo 命令编辑 /etc/sudoers 文件时报错 “/etc/sudoers 忙,请稍后重试”

一、目的 在Linux上用visudo 命令编辑 /etc/sudoers 文件时报错&#xff0c;/etc/sudoers 忙&#xff0c;请稍后重试 [roothurys23 ~]# sudo visudo visudo: /etc/sudoers 忙&#xff0c;请稍后重试 二、原因分析 1 另一个 visudo 实例正在运行 如果另一个用户或同一个用户…

Mirror学习笔记(一) 简介

文章目录 一、常规学习&#xff1a;Mirror核心功能有服务器和主机 二、时间戳批处理时间戳 三、TCP和UDP四、CCU(同时在线人数)五、SyncDirection(同步方向)六、RTT&#xff08;往返时间&#xff09;七、Connection Quality&#xff08;连接质量&#xff09;八、Lag Compensati…

django档案馆集中管理系统-计算机毕业设计源码31775

目录 摘要 Abstract 第一章 绪论 1.1 选题背景及意义 1.2 国内外研究现状 1.3 研究方法 第二章 相关技术介绍 2.1 MySQL简介 2.2 Python 2.3 Django框架 2.4 Pycharm简介 第三章 档案馆集中管理系统系统分析 3.1 系统可行性分析 3.1.1 技术可行性 3.1.2 经济可行…

FFmpeg研究

1.FFmpeg介绍 FFmpeg的全称是“Fast Forward Moving Picture Expert Group”&#xff0c;组件由命令行应用程序和函数库两部分组成。通俗概括来说&#xff0c;FFmpeg 是一个免费的开源程序库&#xff0c;一个多媒体音视频处理分析工具软件&#xff0c;且提供命令行方式调用&am…

Linux(1)--VMware的安装与配置

Linux Linux是一种自由和开放源码的类Unix操作系统&#xff0c;由林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;于1991年首次发布。Linux以其高效性、灵活性和稳定性而闻名&#xff0c;广泛应用于各种计算机硬件设备中&#xff0c;包括手机、平板电脑、路由器、视频游戏…

【Win10】记一次蓝屏修复

最近电脑蓝屏了好多次&#xff0c;错误代码为&#xff1a;IRQL_NOT_LESS_OR_EQUAL 直接搜这个错误代码不太好找原因&#xff0c;于是按照这篇文章[1]来打开错误日志文件。 需要先在windows的应用商店中下载WinDbg 然后&#xff0c;打开目录 C:\Windows\Minidump &#xff0c;…

React 学习——组件内通信(兄弟之间)

A组件 > B组件 核心思路&#xff1a; 1、A组件先通过子传父的方式把数据传给父组件App 2、App拿到数据后通过父传子的方式再传递给B组件 import { useState } from "react" function A({onGetMsg}){const AMsg 我是A组件的消息return (<div><button…

如何实现全国产业园数量扩展,小编带你共同探讨树莓集团产业园运营模式

在当前快速发展的经济环境中&#xff0c;产业园区作为促进经济发展和技术创新的重要平台&#xff0c;扮演着越来越重要的角色。通过精心策划的战略布局与科学严谨的发展规划&#xff0c;树莓集团依托持续的创新驱动与科技引领&#xff0c;成功实现了全国产业园数量的显著扩展与…

【HTML入门】第二十课 - 【实战】做一个侧边栏菜单

这一小节&#xff0c;我们还是继续练习纯HTML标签的内容&#xff0c;多练一些&#xff0c;把HTML标签练熟。这就像练武功前的扎马步和一些基本功&#xff0c;功底越深&#xff0c;后边才能练更高深的武功。 这一小节&#xff0c;我们用纯HTML标签做一个侧边栏菜单的功能。就像这…