设计模式之组合模式解析

组合模式
1)概述
1.定义

组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。

组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又称为“整体—部分”(Part-Whole)模式。

2.结构图

在这里插入图片描述

3.角色
  • Component(抽象构件):它可以是接口或抽象类,为叶子构件和容器构件对象声明的接口,在该角色中可以包含所有子类共有行为的声明和实现,在抽象构件中定义了访问及管理它的子构件的方法,如增加子构件、删除子构件、获取子构件等。

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

  • Composite(容器构件):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法。

4.核心

定义一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。

为容器对象与抽象构件类之间建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。

2)案例-简单方案

抽象构件角色

abstract class Component {
    public abstract void add(Component c); //增加成员
    public abstract void remove(Component c); //删除成员
    public abstract Component getChild(int i); //获取成员
    public abstract void operation();  //业务方法
}

叶子构件

class Leaf extends Component {
    public void add(Component c) {
        //异常处理或错误提示 
    }

    public void remove(Component c) {
        //异常处理或错误提示 
    }

    public Component getChild(int i) {
        //异常处理或错误提示
        return null;
    }

    public void operation() {
        //叶子构件具体业务方法的实现
    }
}

注意:在叶子构件中实现子构件管理和访问方法时需要提供异常处理或错误提示。

容器构件

public class Composite extends Component {
    private final ArrayList<Component> list = new ArrayList<Component>();

    public void add(Component c) {
        list.add(c);
    }

    public void remove(Component c) {
        list.remove(c);
    }

    public Component getChild(int i) {
        return list.get(i);
    }

    public void operation() {
        //容器构件具体业务方法的实现
        //递归调用成员构件的业务方法
        for (Component obj : list) {
            obj.operation();
        }
    }
}
3)案例-完整解决方案
1.结构图

在这里插入图片描述

AbstractFile充当抽象构件类,Folder充当容器构件类,ImageFile、TextFile和VideoFile充当叶子构件类。

2.代码案例

抽象文件类

//抽象文件类:抽象构件
abstract class AbstractFile {
    public abstract void add(AbstractFile file);

    public abstract void remove(AbstractFile file);

    public abstract AbstractFile getChild(int i);

    public abstract void killVirus();
}

具体文件类

//图像文件类:叶子构件
public class ImageFile extends AbstractFile {
    private String name;

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

    public void add(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    public void remove(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    public AbstractFile getChild(int i) {
        System.out.println("对不起,不支持该方法!");
        return null;
    }

    public void killVirus() {
        //模拟杀毒
        System.out.println("----对图像文件'" + name + "'进行杀毒");
    }
}

//文本文件类:叶子构件
public class TextFile extends AbstractFile {
    private String name;

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

    public void add(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    public void remove(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    public AbstractFile getChild(int i) {
        System.out.println("对不起,不支持该方法!");
        return null;
    }

    public void killVirus() {
        //模拟杀毒
        System.out.println("----对文本文件'" + name + "'进行杀毒");
    }
}


//视频文件类:叶子构件
public class VideoFile extends AbstractFile {
    private String name;

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

    public void add(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    public void remove(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    public AbstractFile getChild(int i) {
        System.out.println("对不起,不支持该方法!");
        return null;
    }

    public void killVirus() {
        //模拟杀毒
        System.out.println("----对视频文件'" + name + "'进行杀毒");
    }
}

文件夹类

import java.util.ArrayList;

//文件夹类:容器构件
public class Folder extends AbstractFile {
    //定义集合fileList,用于存储AbstractFile类型的成员
    private ArrayList<AbstractFile> fileList = new ArrayList<AbstractFile>();
    private String name;

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

    public void add(AbstractFile file) {
        fileList.add(file);
    }

    public void remove(AbstractFile file) {
        fileList.remove(file);
    }

    public AbstractFile getChild(int i) {
        return (AbstractFile) fileList.get(i);
    }

    public void killVirus() {
        System.out.println("****对文件夹'" + name + "'进行杀毒");  //模拟杀毒

        //递归调用成员构件的killVirus()方法
        for (Object obj : fileList) {
            ((AbstractFile) obj).killVirus();
        }
    }
}

客户端类

public class Client {
    public static void main(String args[]) {
        //针对抽象构件编程
        AbstractFile file1, file2, file3, file4, file5, folder1, folder2, folder3, folder4;

        folder1 = new Folder("Sunny的资料");
        folder2 = new Folder("图像文件");
        folder3 = new Folder("文本文件");
        folder4 = new Folder("视频文件");

        file1 = new ImageFile("小龙女.jpg");
        file2 = new ImageFile("张无忌.gif");
        file3 = new TextFile("九阴真经.txt");
        file4 = new TextFile("葵花宝典.doc");
        file5 = new VideoFile("笑傲江湖.rmvb");

        folder2.add(file1);
        folder2.add(file2);
        folder3.add(file3);
        folder3.add(file4);
        folder4.add(file5);
        folder1.add(folder2);
        folder1.add(folder3);
        folder1.add(folder4);

        //从“Sunny的资料”节点开始进行杀毒操作
        folder1.killVirus();
    }
}
4)透明组合模式与安全组合模式
1.透明组合模式

a) 概述

在抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法。

b)优点

确保所有的构件类都有相同的接口,在客户端看来,叶子对象与容器对象提供的方法是一致的,客户端可以相同地对待所有的对象。

c)缺点

不够安全,因为叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供add()、remove()以及getChild()等方法是没有意义的,在运行阶段如果调用这些方法可能会出错(如果没有提供相应的错误处理代码)。

d) 结构图

在这里插入图片描述

2.安全组合模式

a)概述

在抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。

b)优点

安全,对于叶子对象,客户端不可能调用到管理成员对象的方法。

c)缺点

不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中用于管理成员对象的方法没有在抽象构件类中定义,因此客户端不能完全针对抽象编程,必须有区别的对待叶子构件和容器构件。

d) 结构图

在这里插入图片描述

5)总结
1.优点
  • 可以清楚地定义分层次的复杂对象,方便对整个层次结构进行控制。

  • 客户端可以一致的使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。

  • 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。

  • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,形成复杂的树形结构。

2.缺点
  • 在增加新构件时很难对容器中的构件类型进行限制。
  • 案例,在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。
3.适用场景

在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。

在一个使用面向对象语言开发的系统中需要处理一个树形结构。

在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。

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

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

相关文章

用Unity3D实现简单的RPG游戏

文章目录 开发流程及关键要素说明**1. **环境设置与项目创建******2. **场景搭建******3. **角色控制******4. **用户输入处理******5. **敌人与战斗系统******6. **物品与装备系统******7. **任务与对话系统******8. **UI与菜单系统******9. **保存与加载系统******10. **测试…

以太网链路聚合——增加带宽,解决生成树收敛慢的问题

目录 一.对STP生成树的补充 1.STP接口状态 2.STP生成树的改进 二.网络可靠性 1.单板可靠性 2.设备可靠性 3.链路可靠性 三.链路聚合 1.多条链路聚合增加带宽 2.链路聚合术语 四.链路聚合模式 1.手动模式 2.LASP模式 &#xff08;1).LASP术语 &#xff08;2&…

SecurityOauth2

引入SpringSecurity SpringSecurity 实现原理是提供了一个过滤器链&#xff0c;其中主要过滤器如下所示&#xff1a; 认证流程示意&#xff1a; 授权过程 SpringSecurity 会使用 FilterSecurityInterceptor 来进行权限校验&#xff0c;在 FilterSecurityInterceptor 中 会从…

Go-js,css,html压缩和混淆(可直接使用)

前提条件: 本地安装nodejs环境然后配置全局环境变量。 运行以下命令安装uglify压缩工具 npm install uglify-js -g 测试是否安装成功 uglifyjs -v 使用方式: 根据不同的操作系统取对应的压缩工具,然后将压缩工具放到项目根目录下,然后执行即可 工具文件: https://gitee.com…

协程库-锁类-实现线程互斥同步

mutex.h&#xff1a;信号量&#xff0c;互斥锁&#xff0c;读写锁&#xff0c;范围锁模板&#xff0c;自旋锁&#xff0c;原子锁 锁 **锁不能进行拷贝操作&#xff1a;**锁是用于管理多线程并发访问共享资源的同步原语。这些锁包括互斥锁&#xff08;mutex&#xff09;、读写锁…

ElementUI中的el-table表格实现动态添加一行、删除一行、清空所有行

ElementUI中的el-table表格实现动态添加一行、删除一行、清空所有行 1、需求分析2、代码实现HTMLdatamethods 1、需求分析 ElementUI中的el-table中实现动态添加一行、删除一行、清空所有行 2、代码实现 HTML <div class"middle-wrapper"><el-buttontype…

Golang hash/crc32 库实战指南:从基础到优化

Golang hash/crc32 库实战指南&#xff1a;从基础到优化 引言理解CRC32hash/crc32库概览实战技巧数据校验性能优化多线程应用 错误处理与调试错误处理调试 实际案例分析结论 总结重点回顾 引言 在现代软件开发中&#xff0c;数据的完整性和安全性至关重要。无论是数据库存储、…

Python抓取抖音直播间数据:技术探索与实践

目录 一、引言 二、技术准备 三、分析抖音直播间网页结构 四、编写爬虫代码 五、处理反爬虫机制 六、数据清洗与存储 七、总结 一、引言 随着互联网的快速发展&#xff0c;直播行业已成为当下的热门领域。抖音作为其中的佼佼者&#xff0c;吸引了大量的用户和主播。对于…

使用vue构建一个简单实用的春节红包插件!

摘要&#xff1a;本文将介绍如何使用Vue.js构建一个简单实用的春节红包插件。该插件通过模拟红包的打开和关闭过程&#xff0c;以及金额的随机分配&#xff0c;为春节红包活动提供了一个有趣且互动的体验。 一、引言 在春节这个充满欢乐和祝福的时刻&#xff0c;红包成为了传递…

Avalonia11.0.2+.Net6.0支持多语言,国际化使用DynamicResource绑定数据

Avalonia11.0.2+.Net6.0支持多语言,国际化使用DynamicResource绑定数据 介绍调整的内容效果展示介绍 本章内容是对上一章博客的补充,当时我们用的是自定义扩展的方式实现了多语言数据的绑定,本章我们用标准的 Text="{DynamicResource 名称}" 来替换 Text="{i…

iphoneX系统的参数

1. 2. 3. 4. 5.相关的网址信息 Apple iPhone X 規格、价格和评论 | Kalvo Apple iPhone X 規格、价格和评论 | Kalvo

Android ViewPager2 setOffscreenPageLimit预加载Fragment,Kotlin

Android ViewPager2 setOffscreenPageLimit预加载Fragment&#xff0c;Kotlin import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androi…

社交革命:Facebook如何塑造数字社交的未来

引言 在当今数字化时代&#xff0c;社交媒体已成为人们生活的核心&#xff0c;而Facebook作为其中的领军者&#xff0c;一直在塑造着数字社交的未来。本文将深入探讨Facebook在数字社交领域的地位、影响力以及对未来社交的塑造作用&#xff0c;为读者揭示这场社交革命如何由Fa…

华为开源自研AI框架昇思MindSpore应用案例:梯度累加

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、案例实现 梯度累加的训练算法&#xff0c;目的是为了解决由于内存不足&#xff0c;导致Batch size过大神经网络无法训练&#xff0c;或者网络模型过大无法加载的OOM&#xff08;Out Of Memory&#xff…

华为实验-基于用户和应用的安全策略

CLI举例&#xff1a;基于用户和应用的安全策略 通过配置安全策略&#xff0c;实现基于用户、时间段以及应用的访问控制。 组网需求 如图1所示&#xff0c;某企业在网络边界处部署了FW作为安全网关。 企业根据员工级别和职能不同划分了三种用户&#xff1a;高层管理者、市场员…

OSG编程指南<二十一>:OSG视图与相机视点更新设置及OSG宽屏变形

1、概述 什么是视图?在《OpenGL 编程指南》中有下面的比喻,从笔者开始学习图形学就影响深刻,相信对读者学习场景管理也会非常有帮助。 产生目标场景视图的变换过程类似于用相机进行拍照,主要有如下的步骤: (1)把照相机固定在三脚架上,让它对准场景(视图变换)。 (2)…

The Annotated Transformer 阅读学习

查资料的间隙发现一篇介绍Transformer的文章&#xff0c;觉得写得很好&#xff0c;但是时间有限一时半会没办法深入去读这里就做了简单的阅读记录&#xff0c;英语水平有限这里只好借助于机器翻译的帮助&#xff0c;将阅读的内容记录下来&#xff0c;等后续有时间再来回顾。 原…

前端-html-02

1.列表 标签名功能和语义属性单标签还是双标签ul无序列表包裹元素双标签 ol 有序列表包裹元素双标签li列表项双标签dl定义列表包裹元素双标签dt定义列表项标题双标签dd定义列表项描述双标签 li必须由Ul或者ol包裹 <!DOCTYPE html> <html><head><…

Linux(CentOS)/Windows-C++ 云备份项目(服务器网络通信模块,业务处理模块设计,断点续传设计)

此模块将网络通信模块和业务处理模块进行了合并 网络通信通过httplib库搭建完成业务处理&#xff1a; 文件上传请求&#xff1a;备份客户端上传的文件&#xff0c;响应上传成功客户端列表请求&#xff1a;客户端请求备份文件的请求页面&#xff0c;服务器响应文件下载请求&…

vector类(一)

文章目录 vector介绍和使用1.vector的介绍2.vector的使用2.1 vector的定义2.2 vector iterator的使用2.3 vector空间增长问题2.4 vector增删查改2.5 vector迭代器失效问题 3.vector 在OJ中的使用 vector介绍和使用 1.vector的介绍 vector是表示 可变大小数组的 序列容器。 就…