组合模式(Composite),将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式解析
角色介绍
Component:组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理 Component 的子部件。
Leaf:在组合中表示叶节点对象,叶节点没有子节点。
Composite:定义有枝节点行为,用来存储子部件,在 Component 接口中实现与子部件有关的操作,比如增加 Add 和删除 Remove。
组合模式基本代码
- Component 类
1 | /** |
2 | * Component |
3 | */ |
4 | public abstract class Component { |
5 | |
6 | private String name; |
7 | |
8 | public Component(String name) { |
9 | this.name = name; |
10 | } |
11 | |
12 | public abstract void add(Component component); |
13 | |
14 | public abstract void remove(Component component); |
15 | |
16 | public abstract void display(); |
17 | |
18 | public String getName() { |
19 | return name; |
20 | } |
21 | |
22 | public void setName(String name) { |
23 | this.name = name; |
24 | } |
25 | } |
- Composite 类
1 | /** |
2 | * Composite |
3 | */ |
4 | public class Composite extends Component { |
5 | /** |
6 | * 存放子节点 |
7 | */ |
8 | List<Component> childCompoents = new LinkedList<>(); |
9 | |
10 | public Composite(String name) { |
11 | super(name); |
12 | } |
13 | |
14 | |
15 | public void add(Component component) { |
16 | this.childCompoents.add(component); |
17 | } |
18 | |
19 | |
20 | public void remove(Component component) { |
21 | this.childCompoents.remove(component); |
22 | } |
23 | |
24 | |
25 | public void display() { |
26 | System.out.println("========" + this.getName() + "=========="); |
27 | // 遍历子节点 |
28 | for (Component c : childCompoents) { |
29 | c.display(); |
30 | } |
31 | } |
32 | } |
- Leaf 类
1 | /** |
2 | * Leaf |
3 | */ |
4 | public class Leaf extends Component { |
5 | |
6 | public Leaf(String name) { |
7 | super(name); |
8 | } |
9 | |
10 | |
11 | public void add(Component component) { |
12 | throw new IllegalStateException("Cannot add to a leaf"); |
13 | } |
14 | |
15 | |
16 | public void remove(Component component) { |
17 | throw new IllegalStateException("Cannot remove from a leaf"); |
18 | } |
19 | |
20 | |
21 | public void display() { |
22 | // 只打印叶子节点,叶子节点没有子节点 |
23 | System.out.println(this.getName()); |
24 | } |
25 | } |
示例
展示一个学校院系结构,一个学校有多个学院,一个学院有多个专业。
类结构图
编码
- OrganizationComponent 类
1 | /** |
2 | * OrganizationComponent |
3 | */ |
4 | public abstract class OrganizationComponent { |
5 | |
6 | private String name; |
7 | |
8 | public OrganizationComponent(String name) { |
9 | this.name = name; |
10 | } |
11 | |
12 | protected abstract void add(OrganizationComponent organizationComponent); |
13 | |
14 | protected abstract void remove(OrganizationComponent organizationComponent); |
15 | |
16 | protected abstract void print(); |
17 | |
18 | public String getName() { |
19 | return name; |
20 | } |
21 | |
22 | public void setName(String name) { |
23 | this.name = name; |
24 | } |
25 | |
26 | } |
- University 类
1 | /** |
2 | * University 就是 Composite , 可以管理 College |
3 | */ |
4 | public class University extends OrganizationComponent { |
5 | |
6 | List<OrganizationComponent> organizationComponents = new LinkedList<>(); |
7 | |
8 | public University(String name) { |
9 | super(name); |
10 | } |
11 | |
12 | |
13 | protected void add(OrganizationComponent organizationComponent) { |
14 | organizationComponents.add(organizationComponent); |
15 | } |
16 | |
17 | |
18 | protected void remove(OrganizationComponent organizationComponent) { |
19 | organizationComponents.remove(organizationComponent); |
20 | } |
21 | |
22 | |
23 | protected void print() { |
24 | System.out.println("--------------" + getName() + "--------------"); |
25 | // 遍历 organizationComponents |
26 | for (OrganizationComponent organizationComponent : organizationComponents) { |
27 | organizationComponent.print(); |
28 | } |
29 | } |
30 | |
31 | } |
- College 类
1 | /** |
2 | * College 学院 |
3 | */ |
4 | public class College extends OrganizationComponent { |
5 | |
6 | /** |
7 | * 存放节点 |
8 | */ |
9 | List<OrganizationComponent> organizationComponents = new LinkedList<OrganizationComponent>(); |
10 | |
11 | public College(String name) { |
12 | super(name); |
13 | } |
14 | |
15 | |
16 | protected void add(OrganizationComponent organizationComponent) { |
17 | // 将来实际业务中,Colleage 的 add 和 University add 不一定完全一样 |
18 | organizationComponents.add(organizationComponent); |
19 | } |
20 | |
21 | |
22 | protected void remove(OrganizationComponent organizationComponent) { |
23 | organizationComponents.remove(organizationComponent); |
24 | } |
25 | |
26 | |
27 | |
28 | protected void print() { |
29 | System.out.println("--------------" + getName() + "--------------"); |
30 | // 遍历 organizationComponents |
31 | for (OrganizationComponent organizationComponent : organizationComponents) { |
32 | organizationComponent.print(); |
33 | } |
34 | } |
35 | |
36 | } |
- Department 类
1 | /** |
2 | * Department |
3 | */ |
4 | public class Department extends OrganizationComponent { |
5 | |
6 | public Department(String name) { |
7 | super(name); |
8 | } |
9 | |
10 | |
11 | protected void add(OrganizationComponent organizationComponent) { |
12 | throw new UnsupportedOperationException(); |
13 | } |
14 | |
15 | |
16 | protected void remove(OrganizationComponent organizationComponent) { |
17 | throw new UnsupportedOperationException(); |
18 | } |
19 | |
20 | |
21 | protected void print() { |
22 | System.out.println(this.getName()); |
23 | } |
24 | } |
- Main 类
1 | public class Main { |
2 | |
3 | public static void main(String[] args) { |
4 | // 学校 |
5 | OrganizationComponent university = new University("清华大学"); |
6 | |
7 | // 创建学院 |
8 | OrganizationComponent infoEngineerCollege = new College("信息工程学院"); |
9 | |
10 | // 创建各个学院下面的专业 |
11 | infoEngineerCollege.add(new Department("软件工程")); |
12 | infoEngineerCollege.add(new Department("网络工程")); |
13 | infoEngineerCollege.add(new Department("计算机科学与技术")); |
14 | |
15 | //将学院加入到学校 |
16 | university.add(infoEngineerCollege); |
17 | |
18 | university.print(); |
19 | } |
20 | } |
小结
在组合模式中,基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。用户是不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。组合模式让客户可以一致地使用组合结构和单个对象。
如果你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。