组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使用户对单个对象和组合对象的使用具有一致性。
Composite Pattern
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
类图
模式的结构与使用
组合方法模式的结构中包括三种角色。 + 抽象组件(Abstract Component):是一个接口(抽象类),该接口(抽象类)定义了个体对象和组合对象需要实现的关于操作其子节点的方法,比如add()、remove()以及getChild()等方法。抽象组件也可以定义个体对象和组合对象用于操作其自身的方法,比如isLeaf()方法等。 + Composite(Composite Node):实现Component接口类的实例,Composite节点不仅实现Component接口,而且可以含有其他Composite节点或Leaf节点的引用。 + Leaf节点(Leaf Node):实现Component接口类的实例,Leaf节点实现Composite接口,不可以含有其他Composite节点或Leaf节点的引用,因此,叶节点在实现Component接口有关操作子节点的方法时,比如add()、remove()和getChild()方法,可让方法抛出一个异常,也可以实现为空操作。
简单的例子
Component的接口类MilitaryPerson.java
package Component;
import java.util.Iterator;
public interface MilitaryPerson {
public void add(MilitaryPerson person);
public void remove(MilitaryPerson person);
public MilitaryPerson
getChild(
int index);
public Iterator<MilitaryPerson>
getAllChildren();
public boolean isLeaf();
public double getSalary();
public void setSalary(
double salary);
}
Composite的实现类MilitaryOfficer.java
package Component;
import java.util.Iterator;
import java.util.LinkedList;
public class MilitaryOfficer implements MilitaryPerson {
LinkedList<MilitaryPerson> list;
String name;
double salary;
public MilitaryOfficer(String name,
double salary) {
this.name = name;
this.salary = salary;
list =
new LinkedList<MilitaryPerson>();
}
@Override
public void add(MilitaryPerson person) {
list.add(person);
}
@Override
public void remove(MilitaryPerson person) {
list.remove(person);
}
@Override
public MilitaryPerson
getChild(
int index) {
return list.get(index);
}
@Override
public Iterator<MilitaryPerson>
getAllChildren() {
return list.iterator();
}
@Override
public boolean isLeaf() {
return false;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void setSalary(
double salary) {
this.salary = salary;
}
}
Leaf的实现类MilitarySoldier.java
package Component;
import java.util.Iterator;
public class MilitarySoldier implements MilitaryPerson {
double salary;
String name;
public MilitarySoldier(
double salary, String name) {
this.salary = salary;
this.name = name;
}
@Override
public void add(MilitaryPerson person) {}
@Override
public void remove(MilitaryPerson person) {}
@Override
public MilitaryPerson
getChild(
int index) {
return null;
}
@Override
public Iterator<MilitaryPerson>
getAllChildren() {
return null;
}
@Override
public boolean isLeaf() {
return true;
}
@Override
public double getSalary() {
return salary;
}
@Override
public void setSalary(
double salary) {
this.salary = salary;
}
}
计算工资的工具类ComputerSalary.java
package Component;
import java.util.Iterator;
public class ComputerSalary {
public static double computerSalary(MilitaryPerson person) {
double sum =
0;
if (person.isLeaf() ==
true) {
sum = sum + person.getSalary();
}
if (person.isLeaf() ==
false) {
sum = sum + person.getSalary();
Iterator<MilitaryPerson> iterator = person.getAllChildren();
while (iterator.hasNext()) {
MilitaryPerson p = iterator.next();
sum = sum + computerSalary(p);
}
}
return sum;
}
}
测试类Application.java
package Component;
public class Application {
public static void main(String[] args) {
MilitaryPerson 连长 =
new MilitaryOfficer(
"连长",
5000);
MilitaryPerson 排长
1 =
new MilitaryOfficer(
"一排长",
4000);
MilitaryPerson 排长
2 =
new MilitaryOfficer(
"二排长",
4000);
MilitaryPerson 排长
3 =
new MilitaryOfficer(
"三排长",
4000);
MilitaryPerson 班长
11 =
new MilitaryOfficer(
"一排长",
2000);
MilitaryPerson 班长
12 =
new MilitaryOfficer(
"二排长",
2000);
MilitaryPerson 班长
13 =
new MilitaryOfficer(
"三排长",
2000);
MilitaryPerson 班长
21 =
new MilitaryOfficer(
"一排长",
2000);
MilitaryPerson 班长
22 =
new MilitaryOfficer(
"二排长",
2000);
MilitaryPerson 班长
23 =
new MilitaryOfficer(
"三排长",
2000);
MilitaryPerson 班长
31 =
new MilitaryOfficer(
"一排长",
2000);
MilitaryPerson 班长
32 =
new MilitaryOfficer(
"二排长",
2000);
MilitaryPerson 班长
33 =
new MilitaryOfficer(
"三排长",
2000);
MilitaryPerson[] 士兵 =
new MilitarySoldier[
90];
for (
int i =
0; i < 士兵.length; i++) {
士兵[i] =
new MilitarySoldier(
1000,
"小兵");
}
连长.add(排长
1);
连长.add(排长
2);
排长
1.add(班长
11);
排长
1.add(班长
12);
排长
1.add(班长
13);
排长
2.add(班长
21);
排长
2.add(班长
22);
排长
2.add(班长
23);
排长
3.add(班长
31);
排长
3.add(班长
32);
排长
3.add(班长
33);
for (
int i =
0; i <=
9; i++) {
班长
11.add(士兵[i]);
班长
12.add(士兵[i +
10]);
班长
13.add(士兵[i +
20]);
班长
21.add(士兵[i +
30]);
班长
22.add(士兵[i +
40]);
班长
23.add(士兵[i +
50]);
班长
31.add(士兵[i +
60]);
班长
32.add(士兵[i +
70]);
班长
33.add(士兵[i +
80]);
}
System.out.println(
"一排的军饷:" + ComputerSalary.computerSalary(排长
1));
System.out.println(
"一班的军饷:" + ComputerSalary.computerSalary(班长
11));
System.out.println(
"全连的军饷:" + ComputerSalary.computerSalary(连长));
}
}
执行效果图
组合模式的优点
组合模式中包含个体对象和组合对象,并形成树形结构,使用户可以方便地处理个体对象和组合对象。组合对象和个体对象实现了相同的接口,用户一般无须区分个体对象和组合对象。当增加新的Composite节点和Leaf节点时,用户的重要代码不需要作出修改,例如,如果增加一个创建企业领导和一般职员的Composite节点和Leaf节点,那么ComputerSalary并不需要修改,就可以计算一个部门的薪水总和。
适用组合模式的情景
当想表示对象的部分-整体层次结构。希望用户用一致的方式处理个体对象和组合对象。
下载源码请到
MyGitHub