【设计模式】第十章:组合模式详解及应用案例

news2024/11/27 8:44:29

系列文章

【设计模式】七大设计原则
【设计模式】第一章:单例模式
【设计模式】第二章:工厂模式
【设计模式】第三章:建造者模式
【设计模式】第四章:原型模式
【设计模式】第五章:适配器模式
【设计模式】第六章:装饰器模式
【设计模式】第七章:代理模式
【设计模式】第八章:桥接模式
【设计模式】第九章:外观模式 / 门面模式
【设计模式】第十章:组合模式
【设计模式】第十一章:享元模式
【设计模式】第十二章:观察者模式
【设计模式】第十三章:模板方法模式
【设计模式】第十四章:策略模式
【设计模式】第十五章:责任链模式
【设计模式】第十六章:迭代器模式
【设计模式】第十七章:状态模式
【设计模式】第十八章:备忘录模式
【设计模式】第十九章:访问者模式
【设计模式】第二十章:解释器模式
【设计模式】第二十一章:命令模式
【设计模式】第二十二章:中介者模式



文章目录

  • 系列文章
  • 一、定义
  • 二、角色分类
  • 三、实现方式
    • UML图
    • 具体实现
      • 透明模式
      • 安全模式
    • 透明模式和安全模式的区别
  • 四、应用场景
  • 五、优缺点
    • 优点
    • 缺点


一、定义

摘自百度百科: 组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。


二、角色分类

抽象构件(Component)

声明了参与组合对象的共有方法和属性,定义了访问其子构件的方法

叶子构件(Leaf)

其表示叶子节点,叶子节点没有子节点,是遍历的最小单位,它实现了在抽象构件中定义的一些行为,

树枝构件(Composite)

它的作用是组合树枝节点和叶子节点构成一个树枝结构,它提供了一个集合来存储子节点,并且实现了抽象构件中定义的行为,包括访问和管理子构件的方法

客户角色(Client)

调用方法的角色


三、实现方式

UML图

Image.png

具体实现

透明模式

抽象构件(Component)

public abstract class Component {
  // 个体与整体都有
  public void operation() {
    // 业务逻辑
  }
  // 增加一个叶子构件或树枝构件
  public abstract void add(Component component);

  // 删除一个叶子构件或树枝构件
  public abstract void remove(Component component);

  // 获取分支下的所有叶子构件和树枝构件
  public abstract List<Component> getChildren();
}

树枝构件(Composite)

public class Composite extends Component {
  // 构件容器
  private List<Component> componentList = new ArrayList<>();

  // 增加一个叶子构件或树枝构件
  public void add(Component component) {
    this.componentList.add(component);
  }

  // 删除一个叶子构件或树枝构件
  public void remove(Component component) {
    this.componentList.remove(component);
  }

  // 获取分支下所有叶子构件和树枝构件
  public List<Component> getChildren() {
    return this.componentList;
  }
}

叶子构件(Leaf)

public class Leaf extends Component {
  public void add(Component component) {
    // 空实现
  }

  public void remove(Component component) {
    // 空实现
  }

  public List<Component> getChildren() {
    // 空实现
  }
}

客户角色(Client)

public class Client {
  public static void main(String[] args) {
    // 创建一个根节点
    Composite root = new Composite();
    root.operation();
    // 创建一个树枝构件
    Composite branch = new Composite();
    // 创建一个叶子节点
    Leaf leaf = new Leaf();
    // 建立整体
    root.add(branch);
    branch.add(leaf);
  }

  public static void showTree(Component root) {
    root.getChildren.foreach(any->{
      if(any instanceof Leaf) {
        // 叶子构件
        any.operation();
      }else {
        // 树枝构件
        showTree(any);
      }
    });
  }
}

安全模式

抽象构件(Component)

public abstract class Component {
  // 个体和整体都有
  public void operation() {
    // 业务逻辑
  }
}

树枝构件(Composite)

public class Composite extends Component {
  // 构件容器
  private List<Component> componentList = new ArrayList<>();

  public void add(Component component){
		this.componentArrayList.add(component);
	}
	// 删除一个叶子构件或树枝构件
	public void remove(Component component){
		this.componentArrayList.remove(component);
	}
	// 获取分支下的所有叶子构件和树枝构件
	public List<Component> getChildren(){
		return this.componentArrayList;
	}
}

叶子构件(Leaf)

public class Leaf extends Component {
  // 可以覆写父类方法
}

客户角色(Client)

public class Client {
  public static void main(String[] args) {
    //创建一个根节点
		Composite root = new Composite();
		root.operation();
		//创建一个树枝构件
		Composite branch = new Composite();
		//创建一个叶子节点
		Leaf leaf = new Leaf();
		//建立整体
		root.add(branch);
		branch.add(leaf);
	}

	//通过递归遍历树
	public static void showTree(Composite root){
		for(Component c:root.getChildren()){
			if(c instanceof Leaf){ 
                // 叶子节点
				c.operation();
			}else{ 
                // 树枝节点
				showTree((Composite)c);
			}
		}
	}
}

透明模式和安全模式的区别

  • 安全模式在抽象组件中只定义一些默认的行为或属性,它是把树枝节点和树叶节点彻底分开;透明模式是把用来组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构,通过判断确认是叶子节点还是树枝节点,如果处理不当,这个会在运行期出现问题,不是很建议的方式。
  • 安全模式与依赖倒置原则冲突;透明模式的好处就是它基本遵循了依赖倒转原则,方便系统进行扩展。
  • 安全模式在遍历树形结构的的时候需要进行强制类型转换;在透明模式下,遍历整个树形结构是比较容易的,不用进行强制类型转换。

四、应用场景

以下部分内容摘自菜鸟教程

意图: 将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

主要解决: 它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

如何解决: 树枝和叶子实现统一接口,树枝内部组合该接口。

关键代码: 树枝内部组合该接口,并且含有内部属性 List,里面放 Component。

应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作数也可以是操作数、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。

使用场景: 部分、整体场景,如树形菜单,文件、文件夹的管理。

注意事项: 定义时为具体类。


五、优缺点

优点

  1. 高层模块调用简单。
  2. 节点自由增加。

缺点

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

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

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

相关文章

【数据可视化】SVG(一)

一、邂逅SVG和初体验 什么是SVG  SVG全称为&#xff08;Scalable Vector Graphics&#xff09;&#xff0c;即可缩放矢量图形。&#xff08;矢量定义&#xff1a;既有大小又有方向的量。在物理学中称作矢量&#xff0c;如一个带箭头线段&#xff1a;长度表示大小&#xff0…

(位运算) 1356. 根据数字二进制下 1 的数目排序 ——【Leetcode每日一题】

❓ 1356. 根据数字二进制下 1 的数目排序 难度&#xff1a;简单 给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。 如果存在多个数字二进制中 1 的数目相同&#xff0c;则必须将它们按照数值大小升序排列。 请你返回排序后的数组。 示…

python flask sqlite http服务

python flask 服务 为了让拼接项目能够简单实用http服务&#xff0c;用python flask 来做一个http服务&#xff0c;使用python的原因是拼接项目本身很多人工智能的服务是用python来写。数据库为了简单实用sqlite&#xff0c;python自带sqlite3 ,很方便 db.sql CREATE TABLE …

AcWing 98. 分形之城

题目链接:AcWing 98. 分形之城 问题描述 分析 这一道题看起来很麻烦&#xff0c;其实就是比较麻烦。 这是一道递归坐标变换的问题&#xff0c;坐标变换比较难想&#xff0c;建议自己动手画一画容易明白一些。 首先是城市等级 n n n 与总点数的关系&#xff0c;不难发现总点数…

golang Redis的新数据类型github.com/go-redis/redis/v8实践

Redis的新数据类型# 在redis中&#xff0c;后面添加了几个比较高级的数据类型 hyperloglog基数统计、GEO存储地理位置、bitmap位图、stream为消息队列设计的数据类型 这 4 种数据类型。 HyperLogLog类型# HyperLogLog简介# HyperLogLog 是一种用于数据统计的集合类型&#x…

亚马逊云科技Zero ETL数据库,助力企业走向数据驱动的业务增长之路

据Forrester研究&#xff0c;相对于数据应用不够成熟的公司&#xff0c;那些有效获取业务洞察的公司&#xff0c;有高达8.5倍的可能性实现至少20%的收入增长。然而&#xff0c;要实现这一增长&#xff0c;需要简化一项流程——在数据分析前管理和准备好数据。这就是为什么亚马逊…

16.电容触摸按键

1.电容触摸按键介绍&#xff1a; R是外接的充电电阻&#xff0c; Cs是没有触摸按下的触摸感应区和四周覆铜区域的一个杂散的电容&#xff1b;当使用手指去触摸感应区时&#xff0c;手指和感应区形成一个电容Cx&#xff0c;开关是电容放电的一个开关&#xff0c;在实际设计中是利…

Ubuntu 22.04.2 LTS LTS x86_64 安装 stable-diffusion-webui 【2】基本版本完结。

前篇 Ubuntu 20.04 LTS x86_64 安装 stable-diffusion-webui_hkNaruto的博客-CSDN博客 内容太多&#xff0c;分第二篇继续 中途重装了机器&#xff0c;20.04 &#xff0c;apt upgrade后自动升级到22.04.2 现状&#xff1a;起来了&#xff0c;又没完全起来 启动日志 (stab…

如何在 Linux 中将本地网络 IP 设置为静态的

文章目录 对于普通的 Linux 操作系统对于 Red Hat Enterprise Linux 9 笔者的运行环境&#xff1a; CentOS 8 Red Hat Enterprise Linux 9 在 Linux 中将本地网络 IP 设置为静态的&#xff0c;只需要在那台 Linux 上设置即可。为了方便&#xff0c;这里笔者使用了 Xshell 来远…

手写操作系统--主引导扇区以及内核加载器

在CPU上电后&#xff0c;会自动将cs:ip置为f000:fff0,下图就是一个计算机刚上电的模拟&#xff1a; ffff00这里开始的代码是BIOS自检&#xff0c;检查计算机的硬件完备性&#xff0c;做完这一切后将第一个扇区的内容复制到0x7c00的位置&#xff0c;并从0x7c00位置执行代码&…

第五章 逻辑回归

第五章 逻辑回归 Logistic回归的⼀般过程 收集数据&#xff1a;采⽤任意⽅法收集数据。准备数据&#xff1a;由于需要进⾏距离计算&#xff0c;因此要求数据类型为数值型。另外&#xff0c;结构化数据格式则最佳。分析数据&#xff1a;采⽤任意⽅法对数据进⾏分析。训练算法&…

Golang每日一练(leetDay0118) 扁平化嵌套列表迭代器、整数拆分

目录 341. 扁平化嵌套列表迭代器 Flatten Nested List Iterator &#x1f31f;&#x1f31f; 343. 整数拆分 Integer Break &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/…

vscode工作区实现机制

工作区是编辑器的重要部分&#xff0c;它承载着编辑器和本地文件的连接&#xff0c;对文件增、删、改、查。下面我会介绍vscode工作区的创建。同样我们知道vscode软件打开的时候没有默认工作区&#xff0c;这里我对它进行了改造&#xff0c;软件启动时指向默认工作区。 工作区目…

提高腾讯QQ(电脑版)语音通话、视频聊天和远程协助的稳定性的方法

一、背景说明 腾讯QQ默认使用的通讯协议是UDP。但是各大运营商将UDP的优先级设置为最低&#xff0c;导致UDP数据包经常被丢弃。导致腾讯QQ在语音通话、视频聊天和远程协助的时候&#xff0c;会出现连接不上、卡顿和断线&#xff0c;非常不稳定。我们可以手动将通讯协议调整为TC…

用Python实现自动化交易:从趋势到收益

在现代金融市场中&#xff0c;自动化交易已经成为越来越流行的一种方式。相比于传统的手工交易方式&#xff0c;自动化交易更加高效、精准、快速且免除了人为因素的影响。而Python作为一种高级编程语言&#xff0c;凭借其简单易学、灵活性强的优势逐渐成为自动化交易中最受欢迎…

Ubuntu下Go语言TCP广播服务器实现

最近在学习Go语言网络编程&#xff0c;突然想到很久以前的用C语言写过的TCP广播聊天程序&#xff0c;然后就用Go尝试写了一遍&#xff0c;在此做个记录。 目录 1.广播结构 2.实现效果 3.源码 4.Go语言学习参考网站 1.广播结构 2.实现效果 服务器&#xff1a; 客户端1&…

小程序 web-view h5页面背景音乐自动播放

/*** 年度账单-登录首页*/ import React,{useEffect} from react import swiper/swiper-bundle.min.css import styles from ./styles.less import bgm from ./bgm2.mp3 // 主体 const annualAccountLoginIndex (props) > {const goAnnualAccount ()>{const {location: …

Java Web Tomcat 23.7.5

Tomcat 1, Tomcat 1.1 简介 1.1.1 什么是Web服务器 Web服务器是一个应用程序&#xff08;软件&#xff09;&#xff0c;对HTTP协议的操作进行封装&#xff0c;使得程序员不必直接对协议进行操作&#xff0c;让Web开发更加便捷。主要功能是"提供网上信息浏览服务"…

[Python系列] Python虚拟环境Virtualenv

1. 什么是Virtualenv Python virtualenv 是一个用于创建和管理虚拟环境的工具。它可以帮助开发者在不同的项目中使用不同的 Python 版本和包&#xff0c;而不会相互干扰。使用 virtualenv&#xff0c;可以轻松地创建一个独立的 Python 环境&#xff0c;在其中安装所需的包和版本…

【网络】思科网络vlan配置+单臂路由

文章目录 前言一、vlan&#xff08;虚拟局域网&#xff09;二、配置vlan配置交换机0配置交换机1&#xff08;和交换机0相同&#xff09;配置计算机&#xff1a;测试联通性 三、单臂路由配置R0配置交换机1测试配置&#xff1a; 前言 VLAN&#xff08;Virtual Local Area Networ…