设计模式之组合模式解析

组合模式
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.适用场景

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

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

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

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

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

相关文章

2024-03-27 问AI: 介绍一下深度学习中的 Darknet

文心一言 在深度学习中&#xff0c;Darknet是一个开源的神经网络框架&#xff0c;由Joseph Redmon开发&#xff0c;主要用于实现深度学习算法。它以其高效的实现和速度受到广泛关注&#xff0c;并在许多计算机视觉竞赛中取得了优异的结果。 Darknet的特点包括&#xff1a; 轻…

学习java第二十五天

a. IOC和DI是什么 控制反转IoC是一种设计思想&#xff0c;而依赖注入DI(Dependency Injection)是IOC的一种实现方法。一般来说&#xff0c;对象的创建源自程序本身&#xff0c;而IoC反转了这种模式&#xff0c;将创建对象的控制转移给了第三方&#xff08;用户&#xff09;。这…

SpringBoot整合Redis:缓存击穿--互斥锁解决

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏Redis实战与进阶 本专栏讲解Redis从原理到实践 …

数字时代的风向标:Facebook如何引领社交媒体的发展方向

引言 在当今数字时代&#xff0c;社交媒体已经成为人们生活中不可或缺的一部分&#xff0c;而Facebook作为其中的领军者&#xff0c;不仅影响着亿万用户的生活&#xff0c;也在塑造着整个社交媒体行业的发展方向。本文将深入探讨Facebook在数字时代的地位、影响力以及对社交媒…

3d放上模型为什么渲染不出来---模大狮模型网

如果在3D软件中放置模型后无法正确渲染出来&#xff0c;可能有几个常见的原因导致这种情况发生&#xff1a; 材质设置问题&#xff1a;确保所放置的模型具有正确的材质和纹理&#xff0c;并且材质设置正确。如果材质设置有误&#xff0c;可能会导致模型无法正确显示。 光照设置…

flink: 从pulsar中读取数据

一、依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0…

配置小程序的服务器域名

准备工作 拥有一个已注册的域名&#xff1a;确保您已经注册了一个符合国家和地区相关法律法规要求的域名。 完成域名备案&#xff08;如有必要&#xff09;&#xff1a;根据国家和地区的法律法规&#xff0c;某些情况下可能需要对域名进行备案才能用于互联网服务。 配置 DNS&…

Vue 二次封装组件的艺术与实践

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

备考ICA----Istio实验9---熔断Circuit Breaking 实验

备考ICA----Istio实验9—熔断Circuit Breaking 实验 1. 环境准备 创建httpbin环境 kubectl apply -f istio/samples/httpbin/httpbin.yaml kubectl get svc httpbin2. 创建测试用客户端 kubectl apply -f istio/samples/httpbin/sample-client/fortio-deploy.yaml3. 创建Ht…

python笔记进阶--模块、文件及IO操作(1)

目录 一&#xff0e;模块 1.模块的导入和使用 1.1导入整个模块 1.2导入函数 1.3使用as给模块指定别名 2.常见标准库 2.1 import random&#xff1a; 2.2 import math&#xff1a; 2.3正则表达式处理 2.4turtle 二&#xff0e;文件及IO操作 1.文件 1.1绝对路径与相…

Intellij IDEA 类注释模板设置

1、配置全局USER 在此配置全局USER&#xff0c;用于填充自动生成的注释中的作者author属性。 注释模板中的user参数是默认是获取系统的用户&#xff08;当然注释作者也可以直接写固定值&#xff09;&#xff0c;如果不想和系统用户用同一个信息&#xff0c;可以在IDEA中进行配…

【自我提升】一、Hyperledger Fabric 概念梳理

写在前面&#xff1a;最近因为业务需要&#xff0c;开始学习Hyperledger Fabric了&#xff0c;做java全栈工程师可真难搞。现在算是啥类型的都在涉及了&#xff0c;现在这个技术啥都不懂&#xff0c;就先开个学习专栏&#xff0c;记录记录。顺带也给各位道友参考参考。 目录 …

「媒体宣传」媒体邀约几种常见方法!-51媒体

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体邀约的常见方法确实包括电话邀约、邮件邀约、社交媒体邀约以及通过媒体公关公司代邀约等。 电话邀约&#xff1a;这是一种直接且高效的方式&#xff0c;可以通过电话与媒体记者沟通&…

HTTP请求走私!!!(一)

想都是问题&#xff0c;做才是答案 什么是请求走私&#xff1f; HTTP请求走私是针对于服务端处理一个或者多个接收http请求序列的方式&#xff0c;进行绕过安全机制&#xff0c;实施未授权访问一种攻击手段&#xff0c;获取敏感信息&#xff0c;并直接危害其他用户。 Web 应用…

【前端学习——css篇】4.px和rem的区别

https://github.com/febobo/web-interview 4.px和rem的区别 ①px px&#xff0c;表示像素&#xff0c;所谓像素就是呈现在我们显示器上的一个个小点&#xff0c;每个像素点都是大小等同的&#xff0c;所以像素为计量单位被分在了绝对长度单位中 有些人会把px认为是相对长度&…

大语言模型(LLM)token解读

1. 什么是token&#xff1f; 人们经常在谈论大模型时候&#xff0c;经常会谈到模型很大&#xff0c;我们也常常会看到一种说法&#xff1a; 参数会让我们了解神经网络的结构有多复杂&#xff0c;而token的大小会让我们知道有多少数据用于训练参数。 什么是token&#xff1f;比…

浅聊openGauss逻辑架构

浅聊 openGauss 逻辑架构 概述 openGauss 数据库是一款由华为主导、各个生态合作伙伴共同建设的开源关系型数据库管理系统&#xff0c;开源发行协议遵从木兰宽松许可证 v2。 openGauss 数据库源于 PostgreSQL-XC 项目&#xff0c;内核源于 Postgres 9.2.4&#xff0c;总代码…

mybatis注解方式if标签报错元素内容必须由格式正确的字符数据或标记组成

在使用mybatis的注解方式的时候出现个问题&#xff0c;我需要一个复杂的sql语句&#xff0c;既有if判断又有in语句&#xff0c;刚开始使用mybatis自己的if动态函数的时候完全没问题&#xff0c;代码如下&#xff1a; Select({"select * ","from order_info &qu…

利用python脚本,根据词条爬取百度图片(爬虫)

把广角&#xff0c;换成你的关键词就行 # -*- coding: utf-8 -*- """ Created on Wed Mar 29 10:17:50 2023 author: MatpyMaster """ import requests import os import redef get_images_from_baidu(keyword, page_num, save_dir):header {Us…

Hadoop+Spark大数据技术 第三次作业

第三次作业 1.简述HDFS Shell三种操作命令hadoop fs、hadoop dfs、hdfs dfs的异同点。 相同点 用于与 Hadoop 分布式文件系统&#xff08;HDFS&#xff09;交互。可以执行各种文件系统操作&#xff0c;如文件复制、删除、移动等。 不同点 hadoop fs、hadoop dfs已弃用&#xf…