一、介绍
组合模式主要用于具有父子关系,或局部-整体关系的情况下。此模式使局部对象和组合对象的使用具有一致性,或者说,我们可以用一个类来统一表示一个对象或组合对象。
二、实例
首先,定义一个抽象的基类,其中定义了局部对象和组合对象的一些基本元素。
import java.util.LinkedList;
import java.util.ListIterator;
public abstract class TeaBags {
LinkedList teaBagList;
TeaBags parent;
String name;
public abstract int countTeaBags();
public abstract boolean add(TeaBags teaBagsToAdd);
public abstract boolean remove(TeaBags teaBagsToRemove);
public abstract ListIterator createListIterator();
public void setParent(TeaBags parentIn) {
parent = parentIn;
}
public TeaBags getParent() {
return parent;
}
public void setName(String nameIn) {
name = nameIn;
}
public String getName() {
return name;
}
}
此段代码中,包含了组合信息的List对象(表示整体)和上下关联的parent对象(指示局部-整体的关系)。
现在,我们基于以上类,定义一个局部对象,其基本定义如下:
import java.util.ListIterator;
public class OneTeaBag extends TeaBags {
public OneTeaBag(String nameIn) {
this.setName(nameIn);
}
public int countTeaBags() {
return 1;
}
public boolean add(TeaBags teaBagsToAdd) {
return false;
}
public boolean remove(TeaBags teaBagsToRemove) {
return false;
}
public ListIterator createListIterator() {
return null;
}
}
然后,定义个一组合对象,定义如下:
import java.util.LinkedList;
import java.util.ListIterator;
public class TinOfTeaBags extends TeaBags {
public TinOfTeaBags(String nameIn) {
teaBagList = new LinkedList();
this.setName(nameIn);
}
public int countTeaBags() {
int totalTeaBags = 0;
ListIterator listIterator = this.createListIterator();
TeaBags tempTeaBags;
while (listIterator.hasNext()) {
tempTeaBags = (TeaBags)listIterator.next();
totalTeaBags += tempTeaBags.countTeaBags();
}
return totalTeaBags;
}
public boolean add(TeaBags teaBagsToAdd) {
teaBagsToAdd.setParent(this);
return teaBagList.add(teaBagsToAdd);
}
public boolean remove(TeaBags teaBagsToRemove) {
ListIterator listIterator =
this.createListIterator();
TeaBags tempTeaBags;
while (listIterator.hasNext()) {
tempTeaBags = (TeaBags)listIterator.next();
if (tempTeaBags == teaBagsToRemove) {
listIterator.remove();
return true;
}
}
return false;
}
public ListIterator createListIterator() {
ListIterator listIterator = teaBagList.listIterator();
return listIterator;
}
}
注意,组合对象TinOfTeaBags实现了add, remove等对局部对象操作的方法,这些个动作也是联系局部和整体的关键。
最后写一个测试类,来使用我们预先布置好的局部类和整体类:
class TestTeaBagsComposite {
public static void main(String[] args) {
System.out.println("Creating tinOfTeaBags");
TeaBags tinOfTeaBags =
new TinOfTeaBags("tin of tea bags");
System.out.println("The tinOfTeaBags has " +
tinOfTeaBags.countTeaBags() +
" tea bags in it.");
System.out.println(" ");
System.out.println("Creating teaBag1");
TeaBags teaBag1 = new OneTeaBag("tea bag 1");
System.out.println("The teaBag1 has " +
teaBag1.countTeaBags() +
" tea bags in it.");
System.out.println(" ");
System.out.println("Creating teaBag2");
TeaBags teaBag2 = new OneTeaBag("tea bag 2");
System.out.println("The teaBag2 has " +
teaBag2.countTeaBags() +
" tea bags in it.");
System.out.println(" ");
System.out.println(
"Putting teaBag1 and teaBag2 in tinOfTeaBags");
if (tinOfTeaBags.add(teaBag1)) {
System.out.println(
"teaBag1 added successfully to tinOfTeaBags");
} else {
System.out.println(
"teaBag1 not added successfully tinOfTeaBags");
}
if (tinOfTeaBags.add(teaBag2)) {
System.out.println(
"teaBag2 added successfully to tinOfTeaBags");
} else {
System.out.println(
"teaBag2 not added successfully tinOfTeaBags");
}
System.out.println("The tinOfTeaBags now has " +
tinOfTeaBags.countTeaBags() +
" tea bags in it.");
System.out.println(" ");
System.out.println("Creating smallTinOfTeaBags");
TeaBags smallTinOfTeaBags =
new TinOfTeaBags("small tin of tea bags");
System.out.println("The smallTinOfTeaBags has " +
smallTinOfTeaBags.countTeaBags() +
" tea bags in it.");
System.out.println("Creating teaBag3");
TeaBags teaBag3 =
new OneTeaBag("tea bag 3");
System.out.println("The teaBag3 has " +
teaBag3.countTeaBags() +
" tea bags in it.");
System.out.println("Putting teaBag3 in smallTinOfTeaBags");
if (smallTinOfTeaBags.add(teaBag3)) {
System.out.println(
"teaBag3 added successfully to smallTinOfTeaBags");
} else {
System.out.println(
"teaBag3 not added successfully to smallTinOfTeaBags");
}
System.out.println("The smallTinOfTeaBags now has " +
smallTinOfTeaBags.countTeaBags() +
" tea bags in it.");
System.out.println(" ");
System.out.println(
"Putting smallTinOfTeaBags in tinOfTeaBags");
if (tinOfTeaBags.add(smallTinOfTeaBags)) {
System.out.println(
"smallTinOfTeaBags added successfully to tinOfTeaBags");
} else {
System.out.println(
"smallTinOfTeaBags not added successfully to tinOfTeaBags");
}
System.out.println("The tinOfTeaBags now has " +
tinOfTeaBags.countTeaBags() +
" tea bags in it.");
System.out.println(" ");
System.out.println("Removing teaBag2 from tinOfTeaBags");
if (tinOfTeaBags.remove(teaBag2)) {
System.out.println(
"teaBag2 successfully removed from tinOfTeaBags");
} else {
System.out.println(
"teaBag2 not successfully removed from tinOfTeaBags");
}
System.out.println("The tinOfTeaBags now has " +
tinOfTeaBags.countTeaBags() +
" tea bags in it.");
}
}
三、分析
通过以上实例,我们可以总结出以下几个关键的角色:
- Compoent 抽象类或接口,用来定义局部-整体的格局,定义公用基本属性,集合属性以及集合对象,定义抽象的add, remove等对局部对象的集合操作方法。
- Leaf 局部对象,或者说是叶子节点,如例子中的OneTeaBag对象。
- Composite 组合对象,实现add, remove等对局部对象的集合操作。
利用组合模式,可以简化客户代码,将组合对象和局部对象统一视为一种对象,忽略它们之间的不同。
如果从数据结构的角度考虑,我们可以把这种对象看成树状结构中的一个节点,它可以是一个叶子节点,也可以是一个分支节点,层层递归,互相变化,但是他们都是这个树的组成部分,可以共享树结点一些共有的属性。