设计模式之组合模式

news2024/12/23 6:25:52

Composite design pattern

组合模式的概念、组合模式的结构、组合模式的优缺点、组合模式的使用场景、组合模式的实现示例、组合模式的源码分析


1、组合模式的概念

  组合模式,即部分整体模式,是用于把一组相似的对象当做一个单一个的对象。组合模式依据树形结构来组合对象,用以表示部分以及整体层次。这种类型的设计模式属于结构形模式,它创建了对象组的树形结构。

2、组合模式的结构

  • 抽象根节点:定义组合中各层次对象的共有行为和属性,可以预先定义一些默认行为和属性。
  • 子节点:继承自抽象根节点,实现其对应的具体行为,定义子节点的行为和属性。
  • 叶子节点:继承自根节点,实现其对应的具体行为,定义叶子节点的行为和属性。

composite-class

  组合模式的分类:

  • 透明组合模式:

    透明组合模式,即抽象根节点角色中定义了所有用于管理成员对象的方法,比如上述类图中的 addNode、removeNode、getNode 等方法。这样做的好处是确保所有构件都有相同的行为,透明组合模式也是组合模式的标准实现。其缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的,可能会出现叶子对象调用容器对象方法的运行错误。

  • 安全组合模式:

    安全组合模式,即抽象根节点角色中没有定义关于管理成员对象的任何方法,而是定义在了容器角色中,这样做的好处是避免了叶子对象调用容器方法而出现的运行错误;缺点是不够透明,客户端不能完全针对抽象编程,必须区别对待叶子构件和容器构件。

3、组合模式的优缺点

  • 优点:
    • 高层次模块调用简单。
    • 节点自由增加,满足开闭原则。
  • 缺点:
    • 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

4、组合模式的使用场景

  • 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致的对待它们。
  • 组合模式正是应树形结构而生,所以在有树形结构的地方可食用。
  • 当一个系统中能够分离出叶子对象和容器对象,且它们的类型不固定,需要增加一些新的类型时。

5、组合模式的实现示例

抽象根节点:

public abstract class MenuComponent {

    protected String name;

    protected Integer level;

    public void addNode(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    public void removeNode(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    public MenuComponent getNode(int index) {
        throw new UnsupportedOperationException();
    }

    public abstract void print();

    public String getName() {
        return this.name;
    }
}

子节点:

public class Menu extends MenuComponent {

    private List<MenuComponent> children;

    public Menu(String name, Integer level) {
        this.name = name;
        this.level = level;
        this.children = new ArrayList<>();
    }

    @Override
    public void addNode(MenuComponent menuComponent) {
        this.children.add(menuComponent);
    }

    @Override
    public void removeNode(MenuComponent menuComponent) {
        this.children.remove(menuComponent);
    }

    @Override
    public MenuComponent getNode(int index) {
        return this.children.get(index);
    }

    @Override
    public void print() {
        for (int i = 1; i < this.level; i++) {
            System.out.print("--");
        }
        System.out.println(this.getName());
        for (MenuComponent child : this.children) {
            child.print();
        }
    }
}

叶子节点:

public class MenuItem extends MenuComponent {

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

    @Override
    public void print() {
        for (int i = 1; i < this.level; i++) {
            System.out.print("--");
        }
        System.out.println(this.getName());
    }
}

测试:

public class CompositeTest {

    public static void main(String[] args) {
        MenuComponent menu = new Menu("系统管理", 1);

        MenuComponent menu1 = new Menu("权限管理", 2);

        MenuComponent menu2 = new Menu("日志管理", 2);

        menu1.addNode(new MenuItem("权限管理", 3));
        menu1.addNode(new MenuItem("角色管理", 3));
        menu1.addNode(new MenuItem("用户管理", 3));

        menu2.addNode(new MenuItem("日志监控", 3));
        menu2.addNode(new MenuItem("告警管理", 3));

        menu.addNode(menu1);
        menu.addNode(menu2);

        menu.print();
    }
}

测试结果:

系统管理
--权限管理
----权限管理
----角色管理
----用户管理
--日志管理
----日志监控
----告警管理

6、组合模式的源码分析

  java.util.map 中的 putAll() 方法的设计实际上使用了组合模式,其可以将 Map 接口的其它字实现类的对象实例放入当前对象自己维护的数据结构中。同理,List 接口中的 addAll() 也使用了组合模式。

public interface Map<K, V> {
  void putAll(Map<? extends K, ? extends V> m);
}
public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {
  public void putAll(Map<? extends K, ? extends V> m) {
        putMapEntries(m, true);
    }
  final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        int s = m.size();
        if (s > 0) {
            if (table == null) { // pre-size
                float ft = ((float)s / loadFactor) + 1.0F;
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                if (t > threshold)
                    threshold = tableSizeFor(t);
            }
            else if (s > threshold)
                resize();
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                K key = e.getKey();
                V value = e.getValue();
                putVal(hash(key), key, value, false, evict);
            }
        }
    }
}

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

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

相关文章

C#语言实例源码系列-身份证验证

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…

【车载开发系列】UDS诊断---数据传输($0x36)

【车载开发系列】UDS诊断—数据传输&#xff08;$0x36&#xff09; UDS诊断---数据传输&#xff08;$0x36&#xff09;【车载开发系列】UDS诊断---数据传输&#xff08;$0x36&#xff09;一.概念定义二.报文格式1&#xff09;请求报文2&#xff09;肯定响应3&#xff09;否定响…

FL Studio21最新中文公测版下载及新功能介绍

FL Studio水果21现已推出&#xff0c;提供更快、更精确的音频编辑&#xff0c;coco玛奇朵升级后的DAW为用户提供了更多的内容发现和改进的界面。 Image-Line发布了FL Studio 21&#xff0c;称其可以实现更快、更精确的音频编辑&#xff0c;以及对整个DAW的更多控制。 期待已久…

【毕业设计_课程设计】基于SSM的实验室管理系统(源码+论文)

文章目录0 项目说明1 研究目的2 研究方法3 项目使用4 研究结论5 论文目录6 项目源码0 项目说明 基于SSM的实验室管理系统 提示&#xff1a;适合用于课程设计或毕业设计&#xff0c;工作量达标&#xff0c;源码开放 1 研究目的 基于B/S模式的实验室管理系统&#xff0c;它所覆…

Linux命令行笔记-00 综述

文章目录1 Linux命令行简介1.1 Linux命令行的分类1.1.1 根据系统中作用来分类1.1.2 根据对象来分类2 Linux命令行解释器2.1 命令行解释器shell2.1.1 核心程序2.1.2 公用程序shell2.1.3 用户的默认shell2.1.4 shell如何工作2.2 Shell发展历史2.3 shell版本的差异2.3.1 C shell2.…

云原生----什么是云原生

【原文链接】云原生----什么是云原生 文章目录1. 云原生的概念2. 云原生的四要素3. 云原生的关键目标什么是云原生&#xff1f;这里将从云原生的概念、云原生的四要素、云原生关键目标等方面介绍。1. 云原生的概念 云原生应用时面向云而设计的应用&#xff0c;在使用云原生技术…

Metasploit Framework和msf框架

Metasploit Framework ● MSF默认集成与kali linux之中 ● 使用postgresql数据库存储数据 ○ 早期版本需要先启动数据库再启动msf MSF架构 Rex ● 基本功能库&#xff0c;用于完成日常基本任务&#xff0c;无需人工手动编码实现 ● 处理socket连接访问、协议应答&#xff08…

洛谷千题详解 | P1020 [NOIP1999 普及组] 导弹拦截【C++语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; C源码2&#xff1a; -------------------------------------------------------------------------------------------------…

【(C语言)数据结构奋斗100天】栈和队列

前言 &#x1f3e0;个人主页&#xff1a;泡泡牛奶 &#x1f335;系列专栏&#xff1a;[C语言] 数据结构奋斗100天 本期所介绍的是栈和队列&#xff0c;那么什么是栈呢&#xff0c;什么是队列呢&#xff1f;在知道答案之前&#xff0c;请大家思考一下下列问题&#xff1a; 你如何…

【问答篇】Java 线程篇 面试题(二)

每天进步一点~ (ps: 文章内容及图片出处来自本人公众号~) 01、问&#xff1a;请谈谈你对线程声明周期的6种状态的认识和理解 答&#xff1a;很多地方说线程有5种状态&#xff0c;但实际上是6种状态:NEW、RUNNABLE, BLOCKED、 WAITING、TIMED_WAITING、TERMINATED; 新创建&a…

(附源码)Springboot掌上博客系统 毕业设计 063131

Springboot掌上博客系统的设计与实现 摘 要 掌上博客系统是当今网络的热点&#xff0c;博客技术的出现使得每个人可以零成本、零维护地创建自己的网络媒体&#xff0c;Blog站点所形成的网状结构促成了不同于以往社区的Blog文化&#xff0c;Blog技术缔造了“博客”文化。 本文课…

微服务框架 SpringCloud微服务架构 服务异步通讯 53 MQ 集群 53.1 集群分类 53.2 普通集群

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 服务异步通讯 文章目录微服务框架服务异步通讯53 MQ 集群53.1 集群分类53.1.1 集群分类53.2 普通集群53.2.1 普通集群53.2.2 搭建普通 集群5…

2022 FIFA World Cup Final

我希望梅西能够捧杯&#xff0c;因为我怕再看见那个眼神&#xff01;写在总决赛开始前 12/18/2022 22:04 在一个周日的晚上收到了邹总发的活动信&#xff0c;我记得还在CSDN问答区在回答问题&#xff0c;突然看见私信的红点&#xff0c;其实看到活动&#xff08;活动链接点击这…

万字长文,彻底搞懂分布式缓存Redis

最近系统性地整理了Redis的知识点&#xff0c;在此和大家做些分享&#xff0c;希望能帮助到大家。 为什么Redis这么受欢迎 时代产物 随着互联网规模的不断扩张&#xff0c;越来越多的企业在技术架构上会采用分布式架构&#xff0c;而且对于系统的吞吐量以及响应速率的要求也…

非零基础自学Golang 第11章 文件操作 11.2 文件基本操作 11.2.3 文件写入 11.2.4 删除文件

非零基础自学Golang 文章目录非零基础自学Golang第11章 文件操作11.2 文件基本操作11.2.3 文件写入11.2.4 删除文件第11章 文件操作 11.2 文件基本操作 11.2.3 文件写入 与之前的文件读取相比&#xff0c;向文件写入内容也有两个接口&#xff0c;分别为Write和WriteAt。 fu…

数据管理篇之元数据

第12章 元数据 1.元数据概述 元数据定义 元数据是关于数据的数据。按照用途可以分为两类&#xff1a; 技术元数据 业务元数据 阿里巴巴常见的技术元数据&#xff1a; 分布式计算系统存储元数据 分布式计算系统运行元数据 数据开发平台中数据同步&#xff0c;计算任务、任务调…

【编译原理】第四章部分课后题答案

第 四 章 课 后 习 题 T 4.1 根据表4.1的语法制导定义&#xff0c;为输入表达式5∗(4∗32)5*(4*32)5∗(4∗32)构造注释分析树。 T 4.2 构造表达式((a∗b)(c))((a*b)(c))((a∗b)(c))的分析树和语法树&#xff1a; &#xff08;a&#xff09;根据表4.3的语法制导定义。 &…

C++中你不知道的namespace和using的用法

目录 引言 一: 冒号作用域 二、名字控制 1 命令空间 2 命令空间的使用 三、 using的指令 1 using的声明 2 using的编译指令 引言 你是不是只认为namespace 和 using 在C中是基本的语法框架&#xff0c;但是却不知道它们的真正用法&#xff0c;看完文章你会对using和name…

计算机毕设Python+Vue校园志愿者服务系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

软件测试零基础如何快速入门 ?这里有全网最详细的学习资料

目录 前言 一、首先&#xff0c;我们要了解清楚用人部门对初级测试人员的定位&#xff1a; 二、清楚了初级测试人员需要具备的能力 三、找到正确的方向 四、最后需要做的就是储备自己的能力。 一.找本软件测试基础的书 二.写文档 三.执行测试 四.多关注技术博文 五、…