当前位置: 首页 > news >正文

组合(整体-部分)模式

简介

组合模式(Composite Pattern)又叫作整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性,属于结构型设计模式。

通用模板

  1. 创建抽象节点接口

    import java.util.List;// 抽象节点
    public interface INode {// 添加一个节点为子节点:INode add(INode node);// 获取子节点:List<INode> children();// 操作String operation();
    }
    
  2. 创建树枝节点

    
    import java.util.ArrayList;
    import java.util.List;// 树枝节点
    public class BranchNode implements INode {private String name;private List<INode> list = new ArrayList<>();public BranchNode(String name) {this.name = name;}@Overridepublic INode add(INode node) {list.add(node);return this;}@Overridepublic List<INode> children() {return list;}@Overridepublic String operation() {StringBuilder builder = new StringBuilder(this.name);for (INode node :list) {builder.append("\n");builder.append(node);}return builder.toString();}@Overridepublic String toString() {return "BranchNode{" +"name='" + name + '\'' +", list=" + list +'}';}
    }
  3. 创建叶子节点

    
    import java.util.ArrayList;
    import java.util.List;// 叶子节点
    public class LeafNode implements INode {private String name;public LeafNode(String name) {this.name = name;}@Overridepublic INode add(INode node) {throw new UnsupportedOperationException();}@Overridepublic List<INode> children() {return new ArrayList<>();}@Overridepublic String operation() {return this.name;}@Overridepublic String toString() {return "LeafNode{" +"name='" + name + '\'' +'}';}
    }

模板测试

  1. 测试代码

    
    public class Client {public static void main(String[] args) {// 创建一个根节点BranchNode root = new BranchNode("root");// 创建一个树枝节点BranchNode branchA = new BranchNode("branch A");BranchNode branchB = new BranchNode("branch B");// 创建一个叶子节点LeafNode leafA = new LeafNode("leaf A");LeafNode leafB = new LeafNode("leaf B");// 给根节点添加树枝节点Aroot.add(branchA);// 给根节点添加树枝节点Broot.add(branchB);// 给树枝节点A添加叶子节点AbranchA.add(leafA);// 给树枝节点B添加叶子节点BbranchB.add(leafB);String result = root.operation();System.out.println(result);}
    }
  2. 结果

    root
    BranchNode{name='branch A', list=[LeafNode{name='leaf A'}]}
    BranchNode{name='branch B', list=[LeafNode{name='leaf B'}, LeafNode{name='leaf C'}]}
    

应用场景

在生活中,组合模式非常常见,比如,树形菜单、公司组织架构和操作系统目录结构等。当子系统与其内各个对象层次呈树形结构时,可以使用组合模式让子系统内各个对象层次的行为操作具备一致性。当客户端使用该子系统内任意一个对象时,不用进行区分,直接使用通用操作即可,非常便捷。
总结一下,组合模式主要有以下应用场景。
(1)希望客户端可以忽略组合对象与单个对象的差异。
(2)对象层次具备整体和部分,呈树形结构。

优点

(1)清楚地定义各层次的复杂对象,表示对象的全部或部分层次。
(2)让客户端忽略了层次的差异,方便对整个层次结构进行控制。
(3)简化客户端代码。
(4)符合开闭原则。

缺点

(1)限制类型时会较为复杂。
(2)使设计变得更加抽象。

“生搬硬套”实战

场景描述

我们来看一个具体的例子。在XML或HTML中,从根节点开始,每个节点都可能包含任意个其他节点,这些层层嵌套的节点就构成了一颗树。

代码开发
  1. 创建抽象节点(这里指的是xml的根节点)接口

    
    import java.util.List;
    // 节点接口
    public interface INode {// 添加一个节点为子节点:INode add(INode INode);// 获取子节点:List<INode> children();// 输出为XML:String toXml();
    }
    
  2. 创建树枝节点(这里指的是xml的元素标签)

    
    // 元素节点
    public class ElementNode implements INode {private String name;private List<INode> list = new ArrayList<>();public ElementNode(String name) {this.name = name;}public INode add(INode INode) {list.add(INode);return this;}public List<INode> children() {return list;}public String toXml() {String start = "<" + name + ">\n";String end = "</" + name + ">\n";StringJoiner sj = new StringJoiner("", start, end);list.forEach(INode -> {sj.add(INode.toXml() + "\n");});return sj.toString();}
    }
    
  3. 创建叶子节点

    
    // 普通文本节点
    public class TextNode implements INode{private String text;public TextNode(String text) {this.text = text;}@Overridepublic INode add(INode INode) {throw new UnsupportedOperationException();}@Overridepublic List<INode> children() {return new ArrayList<>();}@Overridepublic String toXml() {return text;}
    }
    
    
    // 注释节点
    public class CommentNode implements INode {private String text;public CommentNode(String text) {this.text = text;}@Overridepublic INode add(INode INode) {throw new UnsupportedOperationException();}@Overridepublic List<INode> children() {return new ArrayList<>();}@Overridepublic String toXml() {return "<!-- " + text + " -->";}
    }

至此,我们就通过“生搬硬套”组合模式的模板设计出一套组合xml的代码,接下来我们进行测试:

  • 测试代码

    public class Client {public static void main(String[] args) {INode root = new ElementNode("school");root.add(new ElementNode("classA").add(new TextNode("Tom")).add(new TextNode("Alice")));root.add(new ElementNode("classB").add(new TextNode("Bob")).add(new TextNode("Grace")).add(new CommentNode("comment...")));System.out.println(root.toXml());}
    }
    
  • 结果

    
    <school>
    <classA>
    Tom
    Alice
    </classA><classB>
    Bob
    Grace
    <!-- comment... -->
    </classB>
    

总结

组合模式一般用来描述整体与部分的关系,它将对象组织到树形结构中,顶层的节点被称为根节点,根节点下面可以包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。。这样,在组合模式中,整个树形结构中的对象都属于同一种类型,带来的好处就是用户不需要辨别是树枝节点还是叶子节点,可以直接进行操作,给用户的使用带来极大的便利。

相关文章:

  • RealSense、ZED 和奥比中光Astra几款主流相机介绍及应用
  • [遇到问题] Word中插入公式横线“-”变成了长连字符
  • centos9 nginx 版本
  • SpringBoot框架下体育馆管理系统的构建
  • Leetcode 887. 鸡蛋掉落
  • SpringBoot启动过程简述 和 SpringCloud 的五大组键
  • C语言编写一个五子棋游戏-代码实例讲解与分析
  • 给 git 添加扩展命令
  • Qt实现远程开关机
  • Flink Lookup Join的工作原理、性能优化和应用场景
  • systemd使用入门
  • 数据结构——顺序表(基础代码题)
  • golang 如何生成唯一的 UUID
  • 一个OpenHarmony rk3568编译问题
  • 品牌增长新引擎:TikTok达人内容营销策略解析
  • Angular 4.x 动态创建组件
  • Laravel 菜鸟晋级之路
  • Laravel 中的一个后期静态绑定
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • mysql_config not found
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • vue-router的history模式发布配置
  • webpack+react项目初体验——记录我的webpack环境配置
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 给Prometheus造假数据的方法
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 回顾2016
  • 算法之不定期更新(一)(2018-04-12)
  • 微信小程序--------语音识别(前端自己也能玩)
  • ​520就是要宠粉,你的心头书我买单
  • ​插件化DPI在商用WIFI中的价值
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #define用法
  • (2)Java 简介
  • (c语言)strcpy函数用法
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (二)WCF的Binding模型
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (六)c52学习之旅-独立按键
  • (南京观海微电子)——I3C协议介绍
  • (七)Flink Watermark
  • (深度全面解析)ChatGPT的重大更新给创业者带来了哪些红利机会
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (四)c52学习之旅-流水LED灯
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转) 深度模型优化性能 调参
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)Unity3DUnity3D在android下调试
  • *p++,*(p++),*++p,(*p)++区别?
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .gitignore文件—git忽略文件