Compose objects into
TREE structures...
所以当碰到树形结构时, 我们就应该考虑是否可以用Composite模式。
下面我们以一般网站的导航栏来做介绍。
没个Item都对应一个节点, 节点存储了导航的URL
组合模式又分为:
。安全模式
。透明模式
那么先来看看安全模式是怎样滴。
定义一个Node抽象类, 灰常简单, 暴露两个属性
public abstract class Node {
private String name;
private String url;
public String getName() {
return name;
}
public String getUrl() {
return url;
}
public Node(String name, String url) {
this.name = name;
this.url = url;
}
}
然后是叶子节点, 叶子节点没有Child, 所以直接从Node继承过来, 不需要修改
public class Leaf extends Node {
public Leaf(String name, String url) {
super(name, url);
}
}
再就是分支节点了
public class Branch extends Node {
// children 里面的元素有可能是 Branch, 也有可能是 Leaf
private List<Node> children = new ArrayList<Node>();
public Branch(String name, String url) {
super(name, url);
}
public void addChild(Node node) {
this.children.add(node);
}
public void removeChild(Node node) {
if (this.children.contains(node))
this.children.remove(node);
}
public List<Node> getChildren() {
return this.children;
}
}
好啦, 看看客户端代码吧:
public class Client {
public static void main(String[] args) {
Node tree = buildTree();
printTreeInfo(tree);
}
private static Node buildTree() {
Branch root = new Branch("root", "/root");
root.addChild(new Leaf("level1-1", "/level1-1"));
root.addChild(new Leaf("level1-2", "/level1-2"));
Branch level1 = new Branch("level1-3", "/level1-3");
level1.addChild(new Leaf("level1-3-2-1", "/level1-3-2-1"));
level1.addChild(new Leaf("level1-3-2-2", "/level1-3-2-2"));
root.addChild(level1);
return root;
}
@SuppressWarnings("unchecked")
private static void printTreeInfo(Node tree) {
if (tree instanceof Leaf) {
System.out.println("Name = " + tree.getName() + "; URL = "
+ tree.getUrl());
} else {
System.out.println("Name = " + tree.getName() + "; URL = "
+ tree.getUrl());
List<Node> children = ((Branch) tree).getChildren();
Iterator iter = children.iterator();
while (iter.hasNext()) {
printTreeInfo((Node) iter.next());
}
}
}
}
执行结果如下:
引用
Name = root; URL = /root
Name = level1-1; URL = /level1-1
Name = level1-2; URL = /level1-2
Name = level1-3; URL = /level1-3
Name = level1-3-2-1; URL = /level1-3-2-1
Name = level1-3-2-2; URL = /level1-3-2-2
介绍完了安全模式, 再来看看透明模式
那本例来说, 所谓透明模式, 其实就是把Branch里面的add, remove, getChildre方法移到Node类里面去, 然后在客户端代码不需要进行类型的强制转换。
Node类改动比较大
public abstract class Node {
private String name;
private String url;
// children 里面的元素有可能是 Branch, 也有可能是 Leaf
private List<Node> children = new ArrayList<Node>();
public String getName() {
return name;
}
public String getUrl() {
return url;
}
public Node(String name, String url) {
this.name = name;
this.url = url;
}
public void addChild(Node node) {
this.children.add(node);
}
public void removeChild(Node node) {
if (this.children.contains(node))
this.children.remove(node);
}
public List<Node> getChildren() {
return this.children;
}
}
Leaf类比支持add, remove, getChildre方法, 应该明确出来
public class Leaf extends Node {
public Leaf(String name, String url) {
super(name, url);
}
@Override
@Deprecated
public void addChild(Node node) {
throw new UnsupportedOperationException();
}
@Override
@Deprecated
public List<Node> getChildren() {
throw new UnsupportedOperationException();
}
@Override
@Deprecated
public void removeChild(Node node) {
throw new UnsupportedOperationException();
}
}
Branch类得到了简化
public class Branch extends Node {
public Branch(String name, String url) {
super(name, url);
}
}
客户端唯一不同的地方就是用超类申明, 并且不用强制转换
Node root = new Branch("root", "/root");
Node level1 = new Branch("level1-3", "/level1-3");
List<Node> children = tree.getChildren();
最后来看看执行结果, 和安全模式也是一样滴
引用
Name = root; URL = /root
Name = level1-1; URL = /level1-1
Name = level1-2; URL = /level1-2
Name = level1-3; URL = /level1-3
Name = level1-3-2-1; URL = /level1-3-2-1
Name = level1-3-2-2; URL = /level1-3-2-2