Gof23设计模式之组合模式

news2024/12/26 21:53:17

1.定义

​组合模式又名部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
在这里插入图片描述

2.结构

组合模式主要包含三种角色:

  • 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。
  • 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。
  • 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位。

3.实现

我们在访问别的一些管理系统时,经常可以看到类似的菜单。一个菜单可以包含菜单项(菜单项是指不再包含其他内容的菜单条目),也可以包含带有其他菜单项的菜单,因此使用组合模式描述菜单就很恰当,我们的需求是针对一个菜单,打印出其包含的所有菜单以及菜单项的名称。
在这里插入图片描述

/**
 * @author 晓风残月Lx
 * @date 2023/7/12 16:38
 *      菜单组件 (抽象根节点)
 */
public abstract class MenuComponent {

    // 菜单组件的名称
    protected String name;
    // 菜单组件的层级
    protected int level;

    // 添加子菜单
    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    // 移除子菜单
    public void remove(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    // 获取指定的子菜单
    public MenuComponent getChild(int index) {
        throw new UnsupportedOperationException();
    }

    // 获取菜单或者菜单项的名称
    public String getName() {
        return name;
    }

    // 打印菜单名称的方法(包含子菜单和子菜单项)
    public abstract void print();

}




import java.util.ArrayList;
import java.util.List;

/**
 * @author 晓风残月Lx
 * @date 2023/7/12 16:43
 *      菜单类(树枝节点)
 */
public class Menu extends MenuComponent {

    // 菜单可以有多个子菜单或者子菜单项
    private List<MenuComponent> menuComponentList = new ArrayList<MenuComponent>();

    public Menu(String name, int level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public void add(MenuComponent menuComponent) {
        menuComponentList.add(menuComponent);
    }

    @Override
    public void remove(MenuComponent menuComponent) {
        menuComponentList.remove(menuComponent);
    }

    @Override
    public MenuComponent getChild(int index) {
        return menuComponentList.get(index);
    }

    @Override
    public void print() {
        // 打印菜单名称
        for(int i = 0; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
        // 打印子菜单名称或者子菜单项名称
        for (MenuComponent menuComponent : menuComponentList) {
            menuComponent.print();
        }
    }
}




/**
 * @author 晓风残月Lx
 * @date 2023/7/12 16:47
 *      菜单项类(叶子节点)
 */
public class MenuItem extends MenuComponent {

    public MenuItem(String name, int level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public void print() {
        for(int i = 0; i < level; i++) {
            System.out.print("--");
        }
        // 打印菜单项的名称
        System.out.println(name);
    }
}




/**
 * @author 晓风残月Lx
 * @date 2023/7/12 16:49
 */
public class Client {

    public static void main(String[] args) {
        // 创建菜单树
        MenuComponent menu1 = new Menu("菜单管理", 2);
        menu1.add(new MenuItem("页面菜单", 3));
        menu1.add(new MenuItem("展开菜单", 3));
        menu1.add(new MenuItem("编辑菜单", 3));

        MenuComponent menu2 = new Menu("权限管理", 2);
        menu2.add(new MenuItem("页面访问", 3));
        menu2.add(new MenuItem("提交保存", 3));

        MenuComponent menu3 = new Menu("角色管理", 2);
        menu3.add(new MenuItem("新增角色", 3));

        // 创建一级菜单
        MenuComponent component = new Menu("系统管理", 1);

        component.add(menu1);
        component.add(menu2);
        component.add(menu3);

        component.print();
    }

}

在这里插入图片描述

4.组合模式的分类

在使用组合模式时,根据抽象构件类的定义形式,我们可将组合模式分为透明组合模式和安全组合模式两种形式。

  • 透明组合模式

    透明组合模式中,抽象根节点角色中声明了所有用于管理成员对象的方法,比如在示例中 MenuComponent 声明了 addremovegetChild 方法,这样做的好处是确保所有的构件类都有相同的接口。透明组合模式也是组合模式的标准形式。

    透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的,叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供 add()、remove() 等方法是没有意义的,这在编译阶段不会出错,但在运行阶段如果调用这些方法可能会出错(如果没有提供相应的错误处理代码)

  • 安全组合模式

    在安全组合模式中,在抽象构件角色中没有声明任何用于管理成员对象的方法,而是在树枝节点 Menu 类中声明并实现这些方法。安全组合模式的缺点是不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件类中定义,因此客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。

5.优点

  • 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。
  • 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。
  • 在组合模式中增加新的树枝节点和叶子节点都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
  • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

6.使用场景

组合模式正是应树形结构而生,所以组合模式的使用场景就是出现树形结构的地方。比如:文件目录显示,多级目录呈现等树形结构数据的操作。

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

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

相关文章

为react项目添加开发/提交规范(前端工程化、eslint、prettier、husky、commitlint、stylelint)

因历史遗留原因&#xff0c;接手的项目没有代码提醒/格式化&#xff0c;包括 eslint、pretttier&#xff0c;也没有 commit 提交校验&#xff0c;如 husky、commitlint、stylelint&#xff0c;与其期待自己或者同事的代码写得完美无缺&#xff0c;不如通过一些工具来进行规范和…

百度智能云“千帆大模型平台”升级,大模型最多、Prompt模板最全—测评结果超预期

目录 写在前面 什么是Prompt 1 体验分享 打开链接 登录注册 申请成功 2 具体使用 2.1 预置模板 2.2 自制模板 创建Prompt模板 2.3 在线测试 引入Prompt模板 问题1 回答1 总结 问题2 回答2 总结 2.4 API调用说明 其请求方式如下 基础说明 Query参数 响应说明 2.5 API调用代码示例…

java中javamail发送带附件的邮件实现方法

java中javamail发送带附件的邮件实现方法 本文实例讲述了java中javamail发送带附件的邮件实现方法。分享给大家供大家参考。具体分析如下&#xff1a; JavaMail&#xff0c;顾名思义&#xff0c;提供给开发者处理电子邮件相关的编程接口。它是Sun发布的用来处理email的API。它…

24届近5年上海交通大学自动化考研院校分析

今天给大家带来的是上海交通大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、上海交通大学 学校简介 上海交通大学是我国历史最悠久、享誉海内外的高等学府之一&#xff0c;是教育部直属并与上海市共建的全国重点大学。经过120多年的不懈努力&#xff0c;上海交…

码出高效_第二章 | 面向对象_下

目录 四. 方法1. 方法签名2. 方法参数1. 形参和实参2. 可变参数 3. 构造方法4. 类内方法5. getter和setter6. 覆写 五. 重载六. 泛型七. 数据类型1. 基本数据类型2. 引用大小3. 包装类型4. 选择包装类型还是基本数据类型5. 字符串 四. 方法 1. 方法签名 方法签名包括方法名称…

PCA和自动编码器:每个人都能理解的算法

一、说明 本文的主要重点是提供主成分分析 &#xff08;PCA&#xff09; 和自动编码器数据转换技术的直观信息。我不打算深入研究支撑这些模型的数学理论&#xff0c;因为已经有大量的资源可用。 二、pca降维和自编码 2.1 pca和自编码的共同点 自动编码器通过组合数据最重要的特…

VMWare虚拟机设置固定ip

1、在主机上刷新并重新获取ip 1、输入以下命令以释放原先的 ip 地址 #windows命令 ipconfig /release #linux/macos命令 sudo dhclient -r2、再输入以下命令以重新获取 ip 地址 #windows命令 windows&#xff1a;ipconfig /renew #linux/macos命令 sudo dhclient2、设置虚拟…

Linux 下设置开机自启动的方法

文章目录 事先准备对于普通的 Linux对于 RedHat Enterprise Linux 9 笔者的运行环境&#xff1a; 设置成功过的 Linux&#xff1a; RedHat Enterprise Linux 9 x86_64 CentOS 8 x86_64 事先准备 进行这个教程之前&#xff0c;必须要先安装好一个 Linux 操作系统。这个 Linux…

windows永久关闭更新

windows图形化页面做的很好&#xff0c;就是一直强制你更新&#xff0c;不管你用不用得到&#xff0c;而且每次更新&#xff0c;电脑就会变慢。看下面多少更新的功能是用不到的。 打开注册表 winr,输入regedit打开注册表 找位置 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microso…

基于 Emscripten + WebAssembly 实现浏览器操作 Excel

一、为什么要造这个轮子 【C】使用WebAssembly在浏览器端操作Excel_wasm文件用什么打开_你的薄荷醇的博客-CSDN博客使用WebAssembly在浏览器端操作Excel_wasm文件用什么打开https://blog.csdn.net/weixin_44305576/article/details/125545900?ops_request_misc%257B%2522requ…

夜骑,需要注意些什么?

晚上骑行相较于白天骑行&#xff0c;存在着更多的危险和挑战。那么&#xff0c;在夜骑时需要注意些什么呢&#xff1f;接下来我将从以下几个方面进行探讨。 首先&#xff0c;我们需要关注夜间骑行的安全问题。由于夜间视线不好&#xff0c;路面状况也难以掌握&#xff0c;因此需…

回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN…

聚观早报|iPhone 15预计9月22日上市;一加Open渲染图曝光

【聚观365】8月7日消息 iPhone 15预计9月22日上市一加Open渲染图曝光Redmi K60至尊版细节曝光小米14 Pro屏幕细节曝光vivo V3正式发布&#xff0c;执着自研“影像芯片” iPhone 15预计9月22日上市 上周有多位消息人士透露&#xff0c;多家合作的电信运营商已要求员工不要在9月…

自动驾驶传感器选型

360的场景&#xff0c;避免有盲区&#xff0c;长距离 Lidar&#xff08;激光雷达&#xff09; 典型特点一圈一圈的&#xff0c;轮廓和很高的位置精度 禾赛的机械雷达 速腾的固态雷达 固态雷达是车规级的&#xff0c;车规级的意思是可以装到量产车上 Radar&#xff08;毫米…

Containerd的两种安装方式

1. 轻量级容器管理工具 Containerd 2. Containerd的两种安装方式 3. Containerd容器镜像管理 4. Containerd数据持久化和网络管理 操作系统环境为centos7u6 1. YUM方式安装 1.1 获取YUM源 获取阿里云YUM源 # wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun…

vsocde里面远程连接服务器报could not esatablish connection xxxx

我在vscode里面远程连接服务器编辑代码时&#xff0c;正常我按F1选择了服务器IP地址&#xff0c;然后让我选在Linux&#xff0c;然后我再输入服务器密码&#xff0c;但是当我选择Linux系统之后直接没出让我输入服务器密码的输入框&#xff0c;而是直接报错 could not esatablis…

node上传文件 + vue3 + elementPlus 组件封装

一、node 1.在node环境中安装multer(node.js中间件)包&#xff0c;用于处理 multipart/form-data 类型的表单数据 npm install --save multer 2.userRouter var express require(express); const multer require(multer) const upload multer({ dest: public/avataruplo…

Unity制作护盾——1、闪电护盾

Unity引擎制作闪电护盾效果 大家好&#xff0c;我是阿赵。   这期做一个闪电护盾的效果。 一、效果说明 可以改变闪电的颜色 可以改变范围 改变贴图的平铺次数&#xff0c;也可以做出各种不同感觉的护盾。 二、原理 这个效果看着很复杂&#xff0c;其实只是用了一张N…

我们来谈谈数据链路层

"啊&#xff0c;其实触手可及&#xff01;" 谈到网络层IP&#xff0c;有很多说法都是说&#xff0c;"IP是决定到达对端主机的能力"。而在实际的网络世界中&#xff0c;在各个节点路由器上&#xff0c;游走的报文也是IP报文&#xff01; 但是&#xff0c…