11、Composite 组合模式 容器与内容的一致性(抽象化) 结构型设计模式
1、Composite模式定义
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。
将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性.
2、示例代码
类图:
类的一览表
定义Entry类
package cn.design.structured.compposite; /**
* @author lin
* @version 1.0
* @date 2020-07-23 17:04
* @Description TODO
*/
public abstract class Entry {
/**
* 获取名字
*
* @return String
*/
public abstract String getName(); /**
* 获取大小
*
* @return int
*/
public abstract int getSize(); /**
* 加入目录条目
*
* @param entry 入参
* @return 返回
*/
public Entry add(Entry entry) {
throw new FileTreatmentException();
} public void printList() { // 显示目录条目
printList("");
} protected abstract void printList(String prefix); // 显示条目前缀 @Override
public String toString() {
return getName() + "(" + getSize() + ")";
}
}
定义FileTreatmentException类
package cn.design.structured.compposite; /**
* @author lin
* @version 1.0
* @date 2020-07-23 17:06
* @Description TODO
*/
public class FileTreatmentException extends RuntimeException {
public FileTreatmentException() {
} public FileTreatmentException(String message) {
super(message);
} }
定义File类
package cn.design.structured.compposite; /**
* @author lin
* @version 1.0
* @date 2020-07-23 17:05
* @Description 文件类
*/
public class File extends Entry {
private String name;
private int size; public File(String name, int size) {
this.name = name;
this.size = size;
} @Override
public String getName() {
return name;
} @Override
public int getSize() {
return size;
} @Override
protected void printList(String prefix) {
System.out.println(prefix + "/" + this);
}
}
定义Directory类
package cn.design.structured.compposite; import java.util.ArrayList;
import java.util.Iterator; /**
* @author lin
* @version 1.0
* @date 2020-07-23 17:05
* @Description TODO
*/
public class Directory extends Entry { private final String name;
private final ArrayList<Entry> directory = new ArrayList<>(); public Directory(String name) {
this.name = name;
} @Override
public String getName() {
return name;
} @Override
public int getSize() {
int size = 0;
for (Entry entry : directory) {
size += entry.getSize();
}
return size;
} @Override
protected void printList(String prefix) {
System.out.println(prefix + "/" + this);
for (Entry entry : directory) {
entry.printList(prefix + "/" + name);
}
} @Override
public Entry add(Entry entry) {
directory.add(entry);
return this;
}
}
定义CompositeMain测试类
package cn.design.structured.compposite; /**
* @author lin
* @version 1.0
* @date 2020-07-23 16:40
* @Description TODO
*/
public class CompositeMain {
public static void main(String[] args) {
try {
System.out.println("Making root entries............");
Entry rooter = new Directory("root");
Entry binder = new Directory("bin");
Entry teador = new Directory("tmp");
Entry under = new Directory("usr");
rooter.add(binder);
rooter.add(teador);
rooter.add(under);
binder.add(new File("yi", 1000));
binder.add(new File("latex", 200000)); System.out.println("");
System.out.println("Making user entries......");
Entry yuki = new Directory("yuki");
Entry hanako = new Directory("tomura");
Entry tomuura = new Directory("tomura");
under.add(yuki);
under.add(hanako);
under.add(tomuura);
yuki.add(new File("diary.html", 1000));
rooter.printList();
} catch (Exception e) {
System.err.println();
}
}
}
运行结果如下:
Making root entries............ Making user entries......
/root(202000)
/root/bin(201000)
/root/bin/yi(1000)
/root/bin/latex(200000)
/root/tmp(0)
/root/usr(1000)
/root/usr/yuki(1000)
/root/usr/yuki/diary.html(1000)
/root/usr/tomura(0)
/root/usr/tomura(0)
与目标VM断开连接, 地址为: ''127.0.0.1:54150', transport: '套接字'', 传输: '{1}' Process finished with exit code 0
3、深入了解
复合模式类图
角色分工
◆Leaf(树叶)
表示“内容”的角色。在该角色中不能放入其他对象。在示例程序中,由File类扮演此角色。
◆Composite (复合物)
表示容器的角色。可以在其中放入Leaf角色和Composite角色。在示例程序中,由Di rectory类扮演此角色。
◆Component
使Leaf角色和Composite角色具有-致性的角色。Composite 角色是Leaf角色和Composite角色的父类。在示例程序中,由Entry类扮演此角色。
◆Client
使用Composite模式的角色。在示例程序中,由Main类扮演此角色。Composite模式的类图如图11-3 所示。在该图中,可以将Composite角色与它内部的Component角色(即Leaf角色或Composite角色)看成是父亲与孩子们的关系。getChild方法的作用是从Component角色获取这些“孩子们”。
4、小结
Composite比较容易理解,想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时,Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。
意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。
优点: 1、高层模块调用简单。2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。
注意事项:定义时为具体类。
公众号:发哥讲
这是一个稍偏基础和偏技术的公众号,甚至其中包括一些可能阅读量很低的包含代码的技术文,不知道你是不是喜欢,期待你的关注。
如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~
● 扫码关注我们
11、Composite 组合模式 容器与内容的一致性(抽象化) 结构型设计模式的更多相关文章
- 2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式
1.什么是适配器模式? 适配器如同一个常见的变压器,也如同电脑的变压器和插线板之间的电源连接线,他们虽然都是3相的,但是电脑后面的插孔却不能直接插到插线板上. 如果想让额定工作电压是直流12伏特的笔记 ...
- 设计模式(九):Composite组合模式 -- 结构型模式
1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对 ...
- 一天一个设计模式——Composite组合模式
一.模式说明 能够使容器与内容物具有一致性,创造出递归结构的模式就是Composite组合模式. 举个例子:计算机中的文件系统中有文件和文件夹的概念,我们知道,文件夹可以包含文件,也可以包含子文件夹, ...
- Composite组合模式(结构型模式)
1.概述 在面向对象系统中,经常会遇到一些具有"容器性质"的对象,它们自己在充当容器的同时,也充当其他对象的容器. 2.案例 需要构建一个容器系统,需要满足以下几点要求: (1). ...
- 设计模式08: Composite 组合模式(结构型模式)
Composite 组合模式(结构型模式) 对象容器的问题在面向对象系统中,我们常会遇到一类具有“容器”特征的对象——即他们在充当对象的同时,又是其他对象的容器. public interface I ...
- C++设计模式-Composite组合模式
Composite组合模式作用:将对象组合成树形结构以表示“部分-整体”的层次结构.Composite使得用户对单个对象和组合对象的使用具有一致性. UML图如下: 在Component中声明所有用来 ...
- 组合模式 合成模式 COMPOSITE 结构型 设计模式(十一)
组合模式(合成模式 COMPOSITE) 意图 将对象组合成树形结构以表示“部分-整体”的层次结构. Composite使得用户对单个对象和组合对象的使用具有一致性. 树形结构介绍 为了便于理解, ...
- 十一、Composite 组合模式
原理: 代码清单 Entity public abstract class Entry { public abstract String getName(); public abstract int ...
- 享元模式 FlyWeight 结构型 设计模式(十五)
享元模式(FlyWeight) “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...
随机推荐
- windows python的多进程
最近打比赛,apply操作极慢,队友使用了线程池,用多核开辟多线程跑,加速. 在阿里平台上,都没问题. 我是win10系统+jupyter notebook 多线程那个模块运行,会显示一直运行,p.c ...
- 整理 Linux下列出目录内容的命令
在 Linux 中,有非常多的命令可以让我们用来执行各种各样的任务.当我们想要像使用文件浏览器一样列出一个目录下的内容时,大家第一时间想到的是 ls 命令.但只有 ls 命令能实现这个目的吗?显然不是 ...
- bzoj3374[Usaco2004 Mar]Special Serial Numbers 特殊编号*
bzoj3374[Usaco2004 Mar]Special Serial Numbers 特殊编号 题意: 求比一个数大的最小的一半以上的数位相同的数.数位数≤100. 题解: 模拟题.从低位枚举到 ...
- 查看进程中占cpu高的线程方法
当在任务管理器中发现有进程占用cpu过高的时候通过下面的指令将进程快照导出到c盘 jstack -l 进程PID > c:/进程PID.stack (此命令生成.stack文件在c盘中,用文本 ...
- Python Ethical Hacking - MAC Address & How to Change(3)
SIMPLE ALGORITHM Goal -> Check if MAC address was changed. Steps: 1. Execute and read ifconfig. ...
- T3 难题 题解
小王在考试中遇到一道难题:方程 a1+a2+„„+an=m 的非负整数解有几个,请你帮他算 一下(这也可以算作他作弊吧). 输入格式 一行,两个以空格隔开的数 n,m,表示方程 a1+a2+„„+an ...
- GEDIT外部工具
首先通过编辑-首选项-插件-外部命令来打开外部命令,然后在工具-Manage External Tools来添加新工具,工具代码使用bash语言. 代码使用方式:+添加新插件,在编辑框中粘贴代码,快捷 ...
- WebView in ScrollView:View not displayed because it is too large to fit into a software layer
报错信息 W/View: WebView not displayed because it is too large to fit into a software layer (or drawing ...
- 贪心法-------Saruman's army
此题的策略是选取可用范围最右边的点,一般来说该点辐射两边,左侧辐射,右侧辐射,所以用两个循环,第一个循环找出该点,第二个循环求出最右边的点 源代码: #include<iostream># ...
- 一文了解JDK12 13 14 GC调优秘籍-附PDF下载
目录 简介 那些好用的VM参数 G1的变化 配置FlightRecorder RAM参数 JDK13中的ZGC RTM支持 总结 简介 想了解JDK12,13,14中的GC调优秘籍吗?想知道这三个版本 ...