组合模式
欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。
# 简介
组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示 “整体 - 部分” 的层次关系。
组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
这种类型的设计模式属于结构型模式。
组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象。
# 组合模式
需求:要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系。uml 类图如下。
# 代码示例
/**
* 组件
*/
@Data
@AllArgsConstructor
public abstract class OrganizationComponent {
private String name; // 名字
private String desc; // 说明
// 在OrganizationComponent抽象类中定义的add和remove方法默认实现是抛出UnsupportedOperationException异常。是为了继承类无需都需要实现add或remove方法,例如,一个没有子组织的部门就无需实现这些方法。
// 但是,如果某个继承OrganizationComponent的类(比如一个可以有子组织的部门类)需要实现add或remove方法,那么该类就需要重写这两个方法,提供其具体的实现。这样,当调用这个子类的add或remove方法时,就会执行子类重写后的方法,而不是父类中的默认实现,因此就不会抛出UnsupportedOperationException异常。
protected void add(OrganizationComponent organizationComponent) {
// 默认实现
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent organizationComponent) {
// 默认实现
throw new UnsupportedOperationException();
}
// 方法print, 做成抽象的, 子类都需要实现
protected abstract void print();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 大学
*/
public class University extends OrganizationComponent {
private List<OrganizationComponent> organizationComponents = new ArrayList<>();
public University(String name, String desc) {
super(name, desc);
}
@Override
protected void print() {
System.out.println("--------------" + getName() + "--------------所有学院如下");
// 遍历 organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
@Override
protected void add(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
@Override
protected void remove(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
}
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
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
/**
* 学院
*/
public class College extends OrganizationComponent {
List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
public College(String name, String desc) {
super(name, desc);
}
// 重写add
@Override
protected void add(OrganizationComponent organizationComponent) {
// 将来实际业务中,Colleage 的 add 和 University add 不一定完全一样
organizationComponents.add(organizationComponent);
}
// 重写remove
@Override
protected void remove(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
@Override
protected void print() {
System.out.println("--------------" + getName() + "--------------所有院系如下");
// 遍历 organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
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
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
/**
* 院系,这个已经是叶子结点了
*/
public class Department extends OrganizationComponent {
public Department(String name, String desc) {
super(name, desc);
}
@Override
protected void print() {
System.out.println(getName());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
// 创建 大学
OrganizationComponent university = new University("清华大学", " 中国顶级大学 ");
// 创建 学院
OrganizationComponent computerCollege = new College("计算机学院", " 计算机学院 ");
OrganizationComponent infoEngineercollege = new College("信息工程学院", " 信息工程学院 ");
// 创建各个学院下面的系(专业)
computerCollege.add(new Department("软件工程", " 软件工程不错 "));
computerCollege.add(new Department("网络工程", " 网络工程不错 "));
computerCollege.add(new Department("计算机科学与技术", " 计算机科学与技术是老牌的专业 "));
infoEngineercollege.add(new Department("通信工程", " 通信工程不好学 "));
infoEngineercollege.add(new Department("信息工程", " 信息工程好学 "));
university.add(computerCollege);
university.add(infoEngineercollege);
university.print();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 说明
简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子 的问题。
具有较强的扩展性。当我们要更改组合对象时,我们只需要调整内部的层次关系, 客户端不用做出任何改动。
方便创建出复杂的层次结构。客户端不用理会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构。
注意
需要遍历组织机构,或者处理的对象具有树形结构时,非常适合使用组合模式。
要求较高的抽象性,如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式。
# 组合模式在 JDK 源码中的使用
// 在 Map 中定义了 put 方法
public interface Map<K,V> {
V put(K key, V value);
void putAll(Map<? extends K, ? extends V> m);
}
1
2
3
4
5
2
3
4
5
// Map 的子类 AbstractMap 抽象类中给定了 put 方法的默认实现(AbstractMap 的子类如果覆盖必须要实现)
public abstract class AbstractMap<K,V> implements Map<K,V> {
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
}
1
2
3
4
5
6
2
3
4
5
6
// 在 AbstractMap 子类 HashMap 中对 put 方法进行了实现
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
// 在 HashMap 类中又维护了一个内部类 Node,操作 put 其实时操作 Node
Node<K,V>[] tab; Node<K,V> p;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
注意
根据上述的说明,可以发现 Map 和 AbstractMap 其实就是一个 Component,而 HashMap 是一个 Composite,Node 是一个 Leaf。
上次更新: 2025/04/12, 07:54:33