小白设计模式:组合模式
定义
将对象组合成树形结构来表现出“整体/部分”的层次结构。组合能让客户以一致性的方式处理个别的对象以及对象组合。
主要组成
抽象组件(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) {//....}
}
复制代码
总结
优点
使得使用方能够以一致性的方式调用接口,来处理对象,而不必关心这个对象是单个叶节点还是一个组合的对象结构。
缺点
安全性与透明性的考虑
应用场景
有一系列对象集合,并且这些对象集合有明显的"整体/部分"的关系,可以构建成树形结构。
微信公众号
小白设计模式:组合模式相关推荐
- 设计模式---组合模式
设计模式---组合模式 什么是组合模式:Composite? 使用场景 代码示例 组合模式模板 组合模式的安全性和透明性 总结 优缺点: 适用场景: 什么是组合模式:Composite? 计算机的文件 ...
- Java设计模式 —— 组合模式(Composite)
Java设计模式 -- 组合模式(Composite) 定义 Composite,组合模式:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性. ...
- JS设计模式--组合模式
JS设计模式–组合模式 昨天学习了白贺翔老师的JS组合模式,现在把我学到的分享出来叭O(∩_∩)O,直接看下面代码 <!DOCTYPE html> <html lang=" ...
- 设计模式----组合模式UML和实现代码
2019独角兽企业重金招聘Python工程师标准>>> 一.什么是组合模式? 组合模式(Composite)定义:将对象组合成树形结构以表示'部分---整体'的层次结构.组合模式使得 ...
- 大话设计模式—组合模式
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...
- java设计模式 组合_JAVA 设计模式 组合模式
用途组合模式 (Component) 将对象组合成树形结构以表示"部分-整体"的层次结构. 组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模式. 结构 ...
- Java常用设计模式————组合模式
引言 组合模式,是一种类似递归算法的结构性设计模式,通过以简单的 List ,组合本类对象,实现树状对象结构的"部分.整体"的层次. 它可以让调用程序不需要关心复杂对象与简单对象的 ...
- C++设计模式-组合模式
目录 基本概念 代码与实例 基本概念 个人感觉Qt的对象树就是运用了这种设计模式!!! 当然,只是个人感觉,本人并没有研究Qt的源码 组合模式(Composite):将对象组合成树形结构以表示'部分- ...
- [Head First设计模式]生活中学设计模式——组合模式
系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...
- 简说设计模式——组合模式
一.什么是组合模式 前面我们讲过Swing(Java进阶篇(六)--Swing程序设计(上)),在Swing中,容器Container和组件如Button.JLabel等等之间的关系就是组合关系,一个 ...
最新文章
- 启示—地点IT高管20在职场心脏经(读书笔记6)
- python导包顺序_2019-03-21 python导入包以及Python程序执行顺序理解
- 【随笔】游戏程序开发必知的10大基础实用算法及其讲解
- 关于卡巴斯基安全免疫区随笔
- 8.2.5: Spring3.0新增的@DependsOn和@Lazy
- 深入剖析全链路灰度技术
- iOS Hacker Xcode玩转arm64汇编基础
- HDU 4121 Xiangqi
- 机器学习的理论知识点总结
- BestCoder Round #67 (div.2) 1001——N bulbs
- 机器学习必备宝典-《统计学习方法》的python代码实现、电子书及课件
- MapReduce: map读取文件的过程
- ftp ---- 匿名用户(实例配置示例1:匿名用户登录)
- 开发软件快捷键(持续更新中)
- 小姐姐公开征婚高智商 IT 男:微信号竟要质数解密?
- Flask + Vue.js : Fullstack Development
- 团队项目需求分析——NABCD
- win2008php一键,WIN2008 一键安装PHP环境PHP5.3+FastCGI
- 7.java IO流
- kubesphere+kubernetes搭建生产环境高可用集群(一)
热门文章
- php 数组重新打乱_PHP 将数组打乱 shuffle 函数
- 安卓开发仿微信图片拖拽_Android 仿微信朋友圈图片拖拽返回
- mysql ibtmp1 太大_mysql5.7 ibtmp1文件过大
- JAVA蓝桥杯:高精度算法
- STM32F103单片机JTAG端口重映射
- 如何画ROC曲线和FROC曲线
- Tensorflow 2 Auto-Encoder
- 老司机 iOS 周报 #67 | 2019-05-13
- Linux shell基础(四)正则表达式与grep命令 beta
- Android:如何从堆栈中还原ProGuard混淆后的代码