Java设计模式--组合模式

组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构。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

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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

文章目录
  1. 1. 组合模式
  2. 2. Composite Pattern
  3. 3. 类图
  4. 4. 模式的结构与使用
  5. 5. 简单的例子
    1. 5.1. Component的接口类MilitaryPerson.java
    2. 5.2. Composite的实现类MilitaryOfficer.java
    3. 5.3. Leaf的实现类MilitarySoldier.java
    4. 5.4. 计算工资的工具类ComputerSalary.java
    5. 5.5. 测试类Application.java
  6. 6. 执行效果图
  7. 7. 组合模式的优点
  8. 8. 适用组合模式的情景
  9. 9. 下载源码请到