1.组合模式介绍
组合模式,主要是用来处理树形结构数据。这里的“数据”,可以简单理解为一组对象集合。
正因为其应用场景的特殊性,数据必须能表示成树形结构,这也导致了这种模式在实际的项目开发中并不那么常用。但是,一旦数据满足树形结构,应用这种模式就能发挥很大的作用,能让代码变得非常简洁。
在Go F的《设计模式》一书中,组合模式是这样定义的:
Compose objects into tree structure to represent part-whole hierarchies.Composite lets client treat individual objects and compositions of objects uniformly.
翻译成中⽂就是:将⼀组对象组织(Compose)成树形结构,以表示⼀种“部分 – 整体”的层次结构。组合让客户端(在很多设计模式书籍中,“客户端”代指代码的使⽤者。)可以统⼀单个对象和组合对象的处理逻辑。
2.
3.代码案例
HdfsNode抽象节点:
public interface HdfsNode { public String getPath(); public String getType(); }
Hdfs目录类:
public class HdfsDirectory implements HdfsNode { private List<HdfsNode> subNodes = new ArrayList<>(); String path = null; /** * 指定绝对路径 * @param path */ public HdfsDirectory(String path){ this.path = path; } /** * 指定父级目录,采用相对路径 * @param parent 上级目录对象 * @param dirName 目录名 */ public HdfsDirectory(HdfsDirectory parent , String dirName){ parent.addChild(this); this.path = parent.getPath() + dirName; } /** * 得到当前目录路径 * @return */ @Override public String getPath() { return path; } @Override public String getType() { return "directory"; } /** * 增加子节点 * @param node */ public void addChild(HdfsNode node){ this.subNodes.add(node); } /** * 移除子节点 * @param node */ public void removeChild(HdfsNode node){ this.subNodes.remove(node); } /** * 返回所有子节点 * @return */ public List<HdfsNode> getChildren(){ return this.subNodes; } }
文件对象类:
/** * Hdfs文件对象 */ public class HdfsFile implements HdfsNode{ private String filename; private HdfsDirectory ossDirectory; /** * 构造方法 * @param dir 指定目录 * @param filename 文件名 */ public HdfsFile(HdfsDirectory dir , String filename) { this.ossDirectory = dir; dir.addChild(this); this.filename = filename; } /** * 得到文件路径 * @return */ @Override public String getPath() { return ossDirectory.getPath() + filename; } @Override public String getType() { return "file"; } }
客户端类:
public class Client { public static void main(String[] args) { //组织目录结构 HdfsDirectory root = new HdfsDirectory("/root"); HdfsDirectory dir1 = new HdfsDirectory(root,"/s1"); HdfsDirectory dir14 = new HdfsDirectory(root,"/s1/s4"); HdfsDirectory dir145 = new HdfsDirectory(root,"/s1/s4/s5"); HdfsDirectory dir2 = new HdfsDirectory(root,"/s2"); HdfsDirectory dir3 = new HdfsDirectory(root,"/s3"); //组织文件存放 HdfsFile fil1 = new HdfsFile(dir1, "/f1.txt"); HdfsFile fil2 = new HdfsFile(dir2, "/f2.png"); HdfsFile fil3 = new HdfsFile(dir3, "/f3.gif"); HdfsFile fil14 = new HdfsFile(dir14, "/f14.txt"); HdfsFile fil145 = new HdfsFile(dir145, "/f145.svg"); //实例化客户端递归打印所有节点路径 Client client = new Client(); client.printNodes(root); } /** * 递归打印所有节点路径 * @param dir */ public void printNodes(HdfsDirectory dir){ List<HdfsNode> children = dir.getChildren(); for (HdfsNode node : children) { System.out.println(node.getPath()); if(node.getType().equals("directory")){ this.printNodes((HdfsDirectory) node); } } String[] args = new String[10]; } }
输出结果:
/root/s1 /root/s1/f1.txt /root/s1/s4 /root/s1/s4/f14.txt /root/s1/s4/s5 /root/s1/s4/s5/f145.svg /root/s2 /root/s2/f2.png /root/s3 /root/s3/f3.gif
4.组合模式总结
1、简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子的问题。
2、具有较强的扩展性。当我们要更改组合对象时,我们只需要调整内部的层次关系,客户端不用做出任何改动
3、方便创建出复杂的层次结构。客户端不用理会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构
4、需要遍历组织机构,或者处理的对象具有树形结构时, 非常适合使用组合模式.