组合模式实际上是一种树形数据结构。以windows目录系统举例,怎么样用java语言描述一个文件夹?
定义一个文件夹类,文件夹类中包含若干个子文件类和若干个文件类。
进一步抽象,把文件夹和文件都看做节点,于是一个文件夹就可以描述为一个节点类,包含若干个子节点。
我们看看组合模式的代码
// 抽象节点 public abstract class Node { protected String name; abstract void add(Node node); abstract void removed(Node node); abstract void foreach(); public String getName() { return name; } public void setName(String name) { this.name = name; } } // 文件类 public class File extends Node { @Override void add(Node node) { } @Override void removed(Node node) { } @Override void foreach() { System.out.println("File name is " + name); } public File(String name) { this.name = name; } } // 文件夹类 import java.util.ArrayList; import java.util.List; public class Folder extends Node { List<Node> nodes = new ArrayList<Node>(); @Override void add(Node node) { nodes.add(node); } @Override void removed(Node node) { nodes.remove(node); } @Override void foreach() { System.out.println("Folder name is " + name); for(Node node : nodes) { node.foreach(); } } public Folder(String name) { this.name = name; } }
测试类
package com.coshaho.learn.component; public class Test { public static void main(String[] args) { Folder root = new Folder("Root"); Folder music = new Folder("Music"); Folder software = new Folder("Software"); root.add(music); root.add(software); File explain = new File("explain.txt"); File moon = new File("moon.mp3"); File word = new File("word.exe"); root.add(explain); music.add(moon); software.add(word); root.foreach(); } }
在实际应用中,我们希望使用json传递树形结构数据,我们希望每层节点定义都一样,不通过类来区分叶子节点和非叶子节点。这个时候我们可以简单的在Node对象中增加一个isLeaf属性,用来表示该节点是否是叶子节点。这种数据结构是一种递归结构,可以使用递归算法解析。
package com.coshaho.learn.component; import java.util.ArrayList; import java.util.List; import org.springframework.util.CollectionUtils; public class TreeNode { private String name; private boolean isLeaf; private List<TreeNode> nodes = new ArrayList<TreeNode>(); private TreeNode(String name, boolean isLeaf) { this.name = name; this.isLeaf = isLeaf; } void add(TreeNode node) { nodes.add(node); } void removed(TreeNode node) { nodes.remove(node); } public String toString() { String nameInfo = "name: " + name; String typeInfo = "isLeaf: " + isLeaf; String value =""; if(isLeaf || CollectionUtils.isEmpty(nodes)) { value = "{" + nameInfo + "," + typeInfo + "}"; } else { String childrenInfo = "children: ["; for(TreeNode node : nodes) { childrenInfo = childrenInfo + node.toString() + ","; } childrenInfo = childrenInfo.substring(0, childrenInfo.length() - 1) + "]"; value = "{" + nameInfo + "," + typeInfo + "," + childrenInfo + "}"; } return value; } public static void main(String[] args) { TreeNode all = new TreeNode("All", false); TreeNode guangdong = new TreeNode("GuangdDong", true); TreeNode sichuan = new TreeNode("SiChuan", false); TreeNode chengdu = new TreeNode("ChengDu", true); all.add(guangdong); all.add(sichuan); sichuan.add(chengdu); System.out.println(all); } }