定义

将对象组合成树形结构来表现出“整体/部分”的层次结构。组合能让客户以一致性的方式处理个别的对象以及对象组合。

主要组成

抽象组件(Component): 为组合中的对象(节点或者组件)声明接口,也可提供默认的接口缺省实现;

节点对象(Leaf): 组合中的叶节点对象,叶节点对象不再拥有子节点;

复合对象(Composite):允许存在多个子部件,需要包含的子部件,并实现对子部件的操作接口;

客户端(Client): 调用端,通过调用Component相关接口,操作组合中的对象;

UML图

透明模式:叶节点和组合对象所拥有的操作都放抽象组件Component,这样客户端调用时,不需要判断节点类型都可以进行api调用,无需类型转换。但是对应的存在安全性的问题,因为叶节点本身并不具备组合对象add、remove、get等等有关子节点的操作api,这样的设计可能导致调用后出现与预期不符的现象,因为客户有可能会做一些无意义 的事情,例如在Leaf 中增加和删除对象等。

安全模式:将组合对象独有的api操作都放在对应的实现类中,好处就是安全性提升,只有组合对象才会提供add、remove、get等操作。缺点就是不够透明,整个树形结构元素使用上,因为Leaf 和Composite具有不同的接口,客户还得区分判断是叶节点或者组合对象,并进行类型转换才可以调用相应的api;

2种方式在于透明性和安全性的互换,这需要在安全性和透明性之间做出权衡选择,在这一模式中,相对于安全性,我们比较强调透明性。如果你选择了安全性,有时你可能会丢失类型信息,并且不得不将一个组件转换成一个组合。这样的类型转换必定不是类型安全的。

框架代码

这边以透明模式为例:

抽象组件(Component):

将默认实现为抛出异常(也可空实现之类的,具体情况具体分析),子类根据需要进行重写

public abstract class Component {public abstract void operation();public void add(Component component) {throw new UnsupportedOperationException();}public void remove(Component component) {throw new UnsupportedOperationException();}public Component get(int index) {throw new UnsupportedOperationException();}
}
复制代码

节点对象(Leaf):

public class Leaf extends Component{@Overridepublic void operation() {//...System.out.println("叶节点自身的操作");}
}
复制代码

复合对象(Composite):

public class Composite extends Component{List<Component> components = new ArrayList<Component>();@Overridepublic void add(Component component) {components.add(component);}@Overridepublic void remove(Component component) {components.remove(component);}@Overridepublic Component get(int index) {return components.get(index);}@Overridepublic void operation() {for (Component component : components) {component.operation();}}
}
复制代码

Client中调用:

    //创建过程一般是对调用端隐藏,Client不需要关系是创建的什么对象Component component = new Composite();Component leaf1 = new Leaf();Component leaf2 = new Leaf();component.add(leaf1);List<Component> list = new ArrayList<>();list.add(component);list.add(leaf2);//Client只要执行自己所需要的操作就行for (Component component : list) {component.operation();}复制代码

具体例子

熟悉的windows文件目录结构就可以看出是组合模式中的树状图。节点可以是文件(Leaf),也可以是目录(Compostite),可以定义出共同的抽象组件(Component)提供接口: open、delete等相关文件操作。

UML图

代码

AbstractFile抽象文件(Component):

public abstract class AbstractFile {String fileName;public AbstractFile(String fileName) {this.fileName = fileName;}public abstract void open();public abstract void delete();public abstract boolean isDirect();public void add(AbstractFile abstractFile) {throw new UnsupportedOperationException();}public void remove(AbstractFile abstractFile) {throw new UnsupportedOperationException();}public AbstractFile get(int index) {throw new UnsupportedOperationException();}
}
复制代码

File文件叶节点(Leaf):

public class File extends AbstractFile{public File(String fileName) {super(fileName);}@Overridepublic void open() {System.out.println("打开文件" + fileName);}@Overridepublic void delete() {System.out.println("删除文件" + fileName);}@Overridepublic boolean isDirect() {return false;}
}
复制代码

Directory目录节点(Composite)

public class Directory extends AbstractFile{List<AbstractFile> files = new ArrayList<>();public Directory(String fileName) {super(fileName);}@Overridepublic void add(AbstractFile abstractFile) {files.add(abstractFile);}@Overridepublic void remove(AbstractFile abstractFile) {files.remove(abstractFile);}@Overridepublic AbstractFile get(int index) {return files.get(index);}@Overridepublic void open() {for (AbstractFile abstractFile : files) {abstractFile.open();}}@Overridepublic void delete() {for (AbstractFile abstractFile : files) {abstractFile.delete();}}@Overridepublic boolean isDirect() {return true;}
}
复制代码

客户端调用

假设进行文件删除:

AbstractFile directory = new Directory("目录");
AbstractFile file1 = new File("文件1");
AbstractFile file2 = new File("文件2");
directory.add(file1);List<AbstractFile> list = new ArrayList<>();
list.add(directory);
list.add(file2);for (AbstractFile abstractFile : list) {abstractFile.delete();
}
复制代码

假设不使用组合模式

已上诉文件目录例子为例,则会导致在一个文件集合中需要针对性的判断该文件类型:

Directory directory = new Directory("目录");
File file1 = new File("文件1");
File file2 = new File("文件2");List<Object> list = new ArrayList<>();
list.add(directory);
list.add(file1);
list.add(file2);for (Object object : list) {if (object instanceof File) {//....}if (object instanceof Directory) {//....}
}
复制代码

总结

优点

使得使用方能够以一致性的方式调用接口,来处理对象,而不必关心这个对象是单个叶节点还是一个组合的对象结构。

缺点

安全性与透明性的考虑

应用场景

有一系列对象集合,并且这些对象集合有明显的"整体/部分"的关系,可以构建成树形结构。

微信公众号

小白设计模式:组合模式相关推荐

  1. 设计模式---组合模式

    设计模式---组合模式 什么是组合模式:Composite? 使用场景 代码示例 组合模式模板 组合模式的安全性和透明性 总结 优缺点: 适用场景: 什么是组合模式:Composite? 计算机的文件 ...

  2. Java设计模式 —— 组合模式(Composite)

    Java设计模式 -- 组合模式(Composite) 定义 Composite,组合模式:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性. ...

  3. JS设计模式--组合模式

    JS设计模式–组合模式 昨天学习了白贺翔老师的JS组合模式,现在把我学到的分享出来叭O(∩_∩)O,直接看下面代码 <!DOCTYPE html> <html lang=" ...

  4. 设计模式----组合模式UML和实现代码

    2019独角兽企业重金招聘Python工程师标准>>> 一.什么是组合模式? 组合模式(Composite)定义:将对象组合成树形结构以表示'部分---整体'的层次结构.组合模式使得 ...

  5. 大话设计模式—组合模式

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...

  6. java设计模式 组合_JAVA 设计模式 组合模式

    用途组合模式 (Component) 将对象组合成树形结构以表示"部分-整体"的层次结构. 组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模式. 结构 ...

  7. Java常用设计模式————组合模式

    引言 组合模式,是一种类似递归算法的结构性设计模式,通过以简单的 List ,组合本类对象,实现树状对象结构的"部分.整体"的层次. 它可以让调用程序不需要关心复杂对象与简单对象的 ...

  8. C++设计模式-组合模式

    目录 基本概念 代码与实例 基本概念 个人感觉Qt的对象树就是运用了这种设计模式!!! 当然,只是个人感觉,本人并没有研究Qt的源码 组合模式(Composite):将对象组合成树形结构以表示'部分- ...

  9. [Head First设计模式]生活中学设计模式——组合模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

  10. 简说设计模式——组合模式

    一.什么是组合模式 前面我们讲过Swing(Java进阶篇(六)--Swing程序设计(上)),在Swing中,容器Container和组件如Button.JLabel等等之间的关系就是组合关系,一个 ...

最新文章

  1. 启示—地点IT高管20在职场心脏经(读书笔记6)
  2. python导包顺序_2019-03-21 python导入包以及Python程序执行顺序理解
  3. 【随笔】游戏程序开发必知的10大基础实用算法及其讲解
  4. 关于卡巴斯基安全免疫区随笔
  5. 8.2.5: Spring3.0新增的@DependsOn和@Lazy
  6. 深入剖析全链路灰度技术
  7. iOS Hacker Xcode玩转arm64汇编基础
  8. HDU 4121 Xiangqi
  9. 机器学习的理论知识点总结
  10. BestCoder Round #67 (div.2) 1001——N bulbs
  11. 机器学习必备宝典-《统计学习方法》的python代码实现、电子书及课件
  12. MapReduce: map读取文件的过程
  13. ftp ---- 匿名用户(实例配置示例1:匿名用户登录)
  14. 开发软件快捷键(持续更新中)
  15. 小姐姐公开征婚高智商 IT 男:微信号竟要质数解密?
  16. Flask + Vue.js : Fullstack Development
  17. 团队项目需求分析——NABCD
  18. win2008php一键,WIN2008 一键安装PHP环境PHP5.3+FastCGI
  19. 7.java IO流
  20. kubesphere+kubernetes搭建生产环境高可用集群(一)

热门文章

  1. php 数组重新打乱_PHP 将数组打乱 shuffle 函数
  2. 安卓开发仿微信图片拖拽_Android 仿微信朋友圈图片拖拽返回
  3. mysql ibtmp1 太大_mysql5.7 ibtmp1文件过大
  4. JAVA蓝桥杯:高精度算法
  5. STM32F103单片机JTAG端口重映射
  6. 如何画ROC曲线和FROC曲线
  7. Tensorflow 2 Auto-Encoder
  8. 老司机 iOS 周报 #67 | 2019-05-13
  9. Linux shell基础(四)正则表达式与grep命令 beta
  10. Android:如何从堆栈中还原ProGuard混淆后的代码