组合模式(结构型)

目录

一、前言

二、透明组合模式

三、安全组合模式

四、总结


一、前言

        组合模式(Composite Pattern)是一种结构型设计模式,将对象组合成树形结构以表示“部分-整体”得层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

        组合模式由以下角色组成:

Component(抽象组件):

一般是接口或者抽象类,是叶子构件和容器构件对象声明接口,抽象出访问以及管理子构件的方法,可以看做是根节点

Leaf(叶子结点):

在组合中表示叶子节点对象,叶子节点没有子节点,也就没有子构件

Composite(复合节点):

复合节点可以包含子节点,子节点可以是叶子节点,也可以是其他复合节点。可以看做是树枝节点

        整个组合模式的结构图:

二、透明组合模式

        组合模式分为透明和安全两种方式,在透明方式中,抽象组件中会声明所有类中的方法,客户端无法区别树叶对象和树枝对象,对客户端是透明的。但在树叶节点中,本来没有添加、删除放大,但却要实现它,是没有意义的。

        比如公司组织建构,公司有总公司,总公司下有财务部门、技术部门等,还有分公司,分公司也有财务部门,技术部门等。如果按照传统方式,总公司的财务部门、技术部门等需要代码实现,分公司的财务部门、技术部门也需要代码实现,但现实中这些部门的职责差不多,分公司其实可以复用总公司的财务部门、技术部门类。

        根据组合模式,我们便有以下代码实现:

        抽象组件Component类,即根节点:

public abstract class Component {


    abstract void add(Component component);

    abstract void remove(Component component);

    abstract void display(int depth);

    abstract void operation();
}

        复合节点Composite类,即树枝节点:

public class Composite extends Component{

    private List<Component> children = new ArrayList<>();

    private String name;

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

    @Override
    void add(Component component) {
        children.add(component);
    }

    @Override
    void remove(Component component) {
        children.remove(component);
    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
        for (Component component : children) {
            component.display(depth + 1);
        }
    }

    @Override
    void operation() {
        for (Component component : children){
            component.operation();
        }
    }
}

        叶子节点财务部门LeafOne类:

public class LeafOne extends Component{

    private String name;
    public LeafOne(String name) {
        this.name = name;
    }

    @Override
    void add(Component component) {

    }

    @Override
    void remove(Component component) {

    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "财务操作");
    }
}

        叶子节点财务部门LeafTwo类:

public class LeafTwo extends Component{
    private String name;
    public LeafTwo(String name) {
        this.name = name;
    }

    @Override
    void add(Component component) {

    }

    @Override
    void remove(Component component) {

    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "技术操作");
    }
}

        客户端调用类:

public class Client {

    public static void main(String[] args) {

        Component component = new Composite("北京总公司");
        component.add(new LeafOne("北京总公司财务部门"));
        component.add(new LeafTwo("北京总公司技术部门"));


        Component component1 = new Composite("上海分公司");
        component1.add(new LeafOne("上海分公司财务部门"));
        component1.add(new LeafTwo("上海分公司技术部门"));
        component.add(component1);



        Component component2 = new Composite("深圳分公司");
        component2.add(new LeafOne("深圳分公司财务部门"));
        component2.add(new LeafTwo("深圳分公司技术部门"));
        component.add(component2);

        System.out.println("公司架构:");
        component.display(1);
        System.out.println("职能:");
        component.operation();

    }
}

        运行结果:

三、安全组合模式

        相较于透明方式的组合模式,安全方式主要在抽象组件中不包含添加、删除操作,客户端调用中区分复合节点和叶子节点。

        抽象组件Component类:

public abstract class Component {

    abstract void display(int depth);

    abstract void operation();
}

        复合节点Composite类:

public class Composite extends Component{
    private List<Component> children = new ArrayList<>();

    private String name;

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

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }
    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
        for (Component component : children) {
            component.display(depth + 1);
        }
    }

    @Override
    void operation() {
        for (Component component : children){
            component.operation();
        }
    }
}

        叶子节点财务部门LeafOne类:

public class LeafOne extends Component {

    private String name;
    public LeafOne(String name) {
        this.name = name;
    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "财务操作");
    }
}

        叶子节点财务部门LeafTwo类:

public class LeafTwo extends Component{
    private String name;
    public LeafTwo(String name) {
        this.name = name;
    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "技术操作");
    }
}

        客户端调用:

public class Client {
    public static void main(String[] args) {
        Composite composite = new Composite("北京总公司");
        composite.add(new LeafOne("北京总公司财务部门"));
        composite.add(new LeafTwo("北京总公司技术部门"));


        Composite composite1 = new Composite("上海分公司");
        composite1.add(new LeafOne("上海分公司财务部门"));
        composite1.add(new LeafTwo("上海分公司技术部门"));
        composite.add(composite1);



        Composite composite2 = new Composite("深圳分公司");
        composite2.add(new LeafOne("深圳分公司财务部门"));
        composite2.add(new LeafTwo("深圳分公司技术部门"));
        composite.add(composite2);

        System.out.println("公司架构:");
        composite.display(1);
        System.out.println("职能:");
        composite.operation();
    }
}

        运行结果:

四、总结

        优点与缺点

优点:

1、高层模块(客户端)调用简单。组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码

2、节点自由增加,更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”

缺点:

1、在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

2、设计较复杂,客户端需要花更多时间理清类之间的层次关系

3、不容易限制容器中的构件

4、不容易用继承的方法来增加构件的新功能

        使用场景:

        当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式。      

        Spring中IOC就使用到组合模式,通过将组件组合成树形结构,实现了对象的依赖关系管理和生命周期控制。比如Spring中的CompositeCacheManager,Spring用来管理多个CacheManager的复合类。

文件系统:

组合模式可以用来表示文件系统的层次结构,使得客户端可以以统一的方式操作文件和文件夹,例如创建、删除、移动等。

组织机构:

组合模式可以用于表示组织机构的层次结构,例如公司的组织结构可以以树形结构来表示,根节点表示公司,子节点表示部门,叶子节点表示员工。使用组合模式可以统一地管理公司的组织结构,例如添加、删除部门或员工,查找某个部门的员工等。

图形界面控件:

图形界面中的控件可以被看作是一个层次结构,例如窗口控件可以包含按钮控件和文本框控件,按钮控件又可以包含图片控件等。组合模式可以用来表示控件的层次结构,使得客户端可以以统一的方式操作控件,例如添加、删除、遍历等。

菜单和菜单项:

在图形界面中,菜单可以包含菜单项,菜单项可以是子菜单或者普通的操作项。组合模式可以用来表示菜单和菜单项的层次结构,使得客户端可以以统一的方式操作菜单和菜单项,例如添加、删除、遍历等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Jmeter内存溢出原因及解决办法

现在越来越多的小伙伴在压力测试过程中选择使用Jmeter&#xff0c;原因是这个工具开源且小巧&#xff0c;而且还支持二次开发。 但是事情都有两面性&#xff0c;利弊共存啊&#xff0c;对比商业软件Loadrunner&#xff0c;Jmeter在高并发&#xff0c;特别是大型项目的高并发&a…

将macOS系统安装到外置硬盘上教程

常常因为Mac昂贵的价格&#xff0c;我们会选择低容量的硬盘版本&#xff0c;造成很多大型游戏都安装不了的尴尬境地。今天&#xff0c;我们要探讨一个非常实用的话题&#xff1a;如何给你的Mac电脑扩容&#xff0c;通过将macOS系统安装到外置硬盘上。这对于希望提升存储空间但又…

计算机组成原理(超详解!!) 第七节 中央处理器(下)

1.微程序控制器 微程序设计技术&#xff1a;利用软件方法来设计硬件的一门技术。 微程序控制器的基本思想&#xff1a; 仿照通常的解题程序的方法&#xff0c;把操作控制信号编成所谓的“微指令”&#xff0c;存放到一个只读存储器里。当机器运行时&#xff0c;一条又一条地…

安全测试工具BurpSuite安装和使用

1.安装 下载地址&#xff1a;https://pan.baidu.com/s/1YJbZGAfVKLsQmNeZYZXEeQ 提取码: yyds 打开cmd&#xff0c;运行以下指令&#xff0c;打开keygen界面&#xff1a; java -jar "C:\soft\BurpSuite v2.1\burp-loader-keygen-2.jar" 点击Run按钮&#xff0c;弹…

5月13号作业

使用消息队列实现的2个终端之间的互相聊天 并使用信号控制消息队列的读取方式&#xff1a; 当键盘按ctrlc的时候&#xff0c;切换消息读取方式&#xff0c;一般情况为读取指定编号的消息&#xff0c;按ctrlc之后&#xff0c;指定的编号不读取&#xff0c;读取其他所有编号的消息…

标准输入输出流(中北大学-程序设计基础(2))

目录 题目 源码 结果示例 题目 输入三角形的三边a,b,c&#xff0c;计算三角形的面积。形成三角形的条件是ab>c,bc>a,ac>b&#xff0c;编写程序&#xff0c;输入a,b,c&#xff0c;检查a,b,c是否满足以上条件&#xff0c;如不满足&#xff0c;由cerr输出有关出错信息…

开眼了,自动化测试还能这样用?

持续集成的自动化测试通常需要将代码、测试用例与持续集成工具进行绑定&#xff0c;以实现自动运行。然而&#xff0c;Apipost的自动化测试功能需要手动操作&#xff0c;并且需要手动查看测试结果。 为了解决这个问题&#xff0c;Apipost推出了持续集成功能&#xff0c;方便同…

基于SpringBoot的酒店(预约)客房管理系统的设计与实现+毕业论文

系统介绍 酒店客房管理系统为酒店管理者和用户、清洁人员提供一个在线管理酒店客房的系统。在网站的设计中&#xff0c;一共分为了两个模块设计&#xff0c;一个是前台模块&#xff0c;一个是后台模块&#xff0c;前台主要用于提供查看客房信息&#xff0c;酒店资讯&#xff0…

计算礼品发放的最小分组数目 - 贪心思维

系列文章目录 文章目录 系列文章目录前言一、题目描述二、输入描述三、输出描述四、java代码五、测试用例 前言 本人最近再练习算法&#xff0c;所以会发布自己的解题思路&#xff0c;希望大家多指教 一、题目描述 又到了一年的末尾&#xff0c;项目组让小明负责为使得参加晚…

八、e2studio VS STM32CubeIDE之内存使用情况窗口

目录 一、概述/目的 二、STM32CubeIDE Build Analyzer 三、e2studio Memory Usage 八、e2studio VS STM32CubeIDE之内存使用情况窗口 一、概述/目的 1、嵌入开发最大特点之一就是资源受限&#xff0c;关注芯片资源使用详情是优秀工程师的技能之一 2、Keil和IAR都不支持内存…

网络库-libcurl介绍

1.简介 libcurl 是一个功能强大的库&#xff0c;支持多种协议&#xff0c;用于数据传输。它广泛应用于实现网络操作&#xff0c;如HTTP、HTTPS、FTP、FTPS、SCP、SFTP等。libcurl 提供了丰富的 API&#xff0c;可以在多种编程语言中使用。 libcurl 主要特点 支持多种协议&am…

CCF-Csp算法能力认证,202209-1如此编码(C++)含解析

前言 推荐书目&#xff0c;在这里推荐那一本《算法笔记》&#xff08;胡明&#xff09;&#xff0c;需要PDF的话&#xff0c;链接如下 「链接&#xff1a;https://pan.xunlei.com/s/VNvz4BUFYqnx8kJ4BI4v1ywPA1?pwd6vdq# 提取码&#xff1a;6vdq”复制这段内容后打开手机迅雷…

MySQL学习3

目录 一.合计/统计函数&#xff1a; 1.合计函数--count&#xff1a; 2.合计函数-sum 3.合计函数-avg 4.合计函数--max/min 二.分组统计&#xff1a; &#xff08;1&#xff09;使用group by子句对列进行分组&#xff1a; &#xff08;2&#xff09;使用having子句对分组…

【网络基础】TCP协议2

TCP建立连接 什么是TCP连接 用于保证可靠性和流量控制维护的某些状态信息&#xff0c;这些信息的组合&#xff0c;包括 Socket、序列号和窗口大小称为连接。 Socket&#xff1a;由 IP 地址和端口号组成 序列号&#xff1a;用来解决乱序问题等 窗口大小&#xff1a;用来做流量…

企业邮箱域名是什么?怎么注册一个企业邮箱域名?

企业邮箱域名是什么&#xff1f;企业邮箱域名是企业申请的专属域名&#xff0c;绑定专属的邮箱域名&#xff0c;能够在发送邮件时提高品牌识别性、专业性和宣传效果。那么&#xff0c;我们该怎么注册一个企业邮箱域名呢&#xff1f;本文将为你详细介绍。 一、企业邮箱域名是什…

揭秘高效引流获客的艺术

在数字营销的海洋中&#xff0c;吸引潜在客户的注意力就像捕捉闪烁的鱼群——需要技巧、耐心和正确的工具。有效的引流获客策略能为企业带来生机&#xff0c;如同春风拂过荒漠&#xff0c;唤醒沉睡的种子。本文将带你领略那些让企业脱颖而出的获客秘籍&#xff0c;让你的目标客…

机器视觉技术精准测量点胶高度与宽度:提升生产质量的新利器

在现代化生产线中&#xff0c;点胶工艺是许多产品制造过程中的重要环节。点胶的高度和宽度直接影响到产品的质量和性能。传统的测量方法往往效率低下、精度不高&#xff0c;而机器视觉技术的引入&#xff0c;为点胶高度和宽度的测量带来了革命性的变革。本文将探讨机器视觉如何…

一文汇总对比英伟达、AMD、英特尔显卡GPU

‍‍&#x1f3e1;博客主页&#xff1a; virobotics(仪酷智能)&#xff1a;LabVIEW深度学习、人工智能博主 &#x1f4d1;上期文章&#xff1a;『【仪酷LabVIEW AI工具包案例】使用LabVIEW AI工具包YOLOv5结合Dobot机械臂实现智能垃圾分类』 &#x1f37b;本文由virobotics(仪酷…

运筹系列92:vrp算法包VROOM

1. 介绍 VROOM is an open-source optimization engine written in C20 that aim at providing good solutions to various real-life vehicle routing problems (VRP) within a small computing time. 可以解决如下问题&#xff1a; TSP (travelling salesman problem) CVRP …

使用Navicat将MySql数据库导入和导出

一&#xff0c;导出数据表 1.使用Navicat打开数据库&#xff0c;右键数据库&#xff0c;点击转储SQL文件&#xff0c;点击结构和数据。 2.选择生成文件的地方 3.等待生成完成 4.生成完成 二&#xff0c;导入数据库表和数据SQL文件 1.新建一个数据库 2.右键选择运行SQl文件 记…