组合模式实际上是一种树形数据结构。以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);
}
}