组合模式的定义:
Compose objects into tree structures to represent part-whole hierarchies . Composite lets clients treat individual objects and compositions of objects uniformly .
将对象组成树形结构来表明部分-整体的层次关系。组合使得课余一致得使用单个对象和组合对象。
组合模式的组成:
1.抽象构件角色Component:它为组合中的对象声明接口,也可以为共有接口实现缺省行为。
2.树叶构件角色Leaf:在组合中表示叶节点对象——没有子节点,实现抽象构件角色声明的接口。
3. 树枝构件角色Composite:在组合中表示分支节点对象——有子节点,实现抽象构件角色声明的接口;存储子部件。
下图为组合模式的类图表示。
安全性与透明性
组合模式中必须提供对子对象的管理方法,不然无法完成对子对象的添加删除等等操作,也就失去了灵活性和扩展性。但是管理方法是在Component中就声明还是在Composite中声明呢?
一种方式是在Component里面声明所有的用来管理子类对象的方法,以达到Component接口的最大化(如下图所示)。目的就是为了使客户看来在接口层次上树叶和分支没有区别——透明性。但树叶是不存在子类的,因此Component声明的一些方法对于树叶来说是不适用的。这样也就带来了一些安全性问题。
另一种方式就是只在Composite里面声明所有的用来管理子类对象的方法(如下图所示)。这样就避免了上一种方式的安全性问题,但是由于叶子和分支有不同的接口,所以又失去了透明性。
《设计模式》一书认为:在这一模式中,相对于安全性,我们比较强调透明性。对于第一种方式中叶子节点内不需要的方法可以使用空处理或者异常报告的方式来解决。
使用组合模式
以下是使用安全的组合模式的类图和示例代码:
package pattern.part3.chapter11.safe;
/**
* Date: 2010-2-20
* Time: 16:26:38
*/
public abstract class BranchComponent {
public String getName() {
throw new UnsupportedOperationException();
}
public String getDiscription() {
throw new UnsupportedOperationException();
}
public void display() {
throw new UnsupportedOperationException();
}
}
package pattern.part3.chapter11.safe;
import java.util.ArrayList;
import java.util.List;
/**
* Date: 2010-2-20
* Time: 16:27:00
*/
public class BranchComposite extends BranchComponent {
private String name;
private String discription;
private List<BranchComponent> childrenBranch;
public BranchComposite(String name, String discription) {
this.name = name;
this.discription = discription;
childrenBranch = new ArrayList<BranchComponent>();
}
public void display() {
System.out.printf("%s: %s\n", name, discription);
for (BranchComponent child : childrenBranch) {
child.display();
}
}
public String getName() {
return name;
}
public String getDiscription() {
return discription;
}
public void add(BranchComponent child) {
childrenBranch.add(child);
}
public void remove(BranchComponent child) {
childrenBranch.remove(child);
}
public BranchComponent getChild(int index) {
return childrenBranch.get(index);
}
}
package pattern.part3.chapter11.safe;
/**
* Date: 2010-2-20
* Time: 16:59:38
*/
public class BranchLeaf extends BranchComponent {
private String name;
private String discription;
public BranchLeaf(String name, String discription) {
this.name = name;
this.discription = discription;
}
public void display() {
System.out.printf("\t%s: %s\n", name, discription);
}
public String getName() {
return name;
}
public String getDiscription() {
return discription;
}
}
package pattern.part3.chapter11.safe;
/**
* Date: 2010-2-20
* Time: 17:12:45
*/
public class TestDrive {
public static void main(String[] args) {
BranchComposite china = new BranchComposite("CN", "China Branch");
BranchComposite shanghai = new BranchComposite("Sh", "Shanghai Branch");
BranchLeaf huangpu = new BranchLeaf("Hp", "Huangpu Branch");
BranchLeaf yangpu = new BranchLeaf("Yp", "Yangpu Branch");
BranchLeaf pudong = new BranchLeaf("Pd", "Pudong Branch");
BranchComposite beijing = new BranchComposite("Bj", "Beijing Branch");
BranchLeaf dongcheng = new BranchLeaf("Dc", "Dongcheng Branch");
BranchLeaf xicheng = new BranchLeaf("Xc", "Xicheng Branch");
BranchLeaf haidian = new BranchLeaf("Hd", "Haidian Branch");
shanghai.add(huangpu);
shanghai.add(yangpu);
shanghai.add(pudong);
beijing.add(dongcheng);
beijing.add(xicheng);
beijing.add(haidian);
china.add(shanghai);
china.add(beijing);
System.out.println("Displaying the head bank information");
display(china);
System.out.println("\nDisplaying Shanghai bank branch information");
display(shanghai);
System.out.println("\nDisplaying Pudong bank branch information in Shanghai");
display(pudong);
}
private static void display(BranchComponent branch) {
branch.display();
}
}
运行结果:
Displaying the head bank information
CN: China Branch
Sh: Shanghai Branch
Hp: Huangpu Branch
Yp: Yangpu Branch
Pd: Pudong Branch
Bj: Beijing Branch
Dc: Dongcheng Branch
Xc: Xicheng Branch
Hd: Haidian Branch
Displaying Shanghai bank branch information
Sh: Shanghai Branch
Hp: Huangpu Branch
Yp: Yangpu Branch
Pd: Pudong Branch
Displaying Pudong bank branch information in Shanghai
Pd: Pudong Branch