笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 设计模式

    • 简介

    • 原则

    • UML

    • 创建型

    • 结构型

      • 适配器模式
      • 桥接模式
      • 装饰者模式
      • 组合模式
        • 简介
        • 组合模式
          • 代码示例
          • 说明
        • 组合模式在 JDK 源码中的使用
      • 外观模式
      • 享元模式
      • 代理模式
    • 行为型

  • JVM 详解

  • Linux

  • Redis

  • 分布式锁

  • Shiro

  • Gradle

  • Java 进阶
  • 设计模式
  • 结构型
EasT-Duan
2023-11-17
目录

组合模式

欢迎来到我的 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
/**
 * 大学
 */
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
/**
 * 学院
 */
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
/**
 * 院系,这个已经是叶子结点了
 */
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
/**
 * 客户端
 */
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

# 说明

简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者节点叶子 的问题。

具有较强的扩展性。当我们要更改组合对象时,我们只需要调整内部的层次关系, 客户端不用做出任何改动。

方便创建出复杂的层次结构。客户端不用理会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构。

注意

需要遍历组织机构,或者处理的对象具有树形结构时,非常适合使用组合模式。

要求较高的抽象性,如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,不适合使用组合模式。

# 组合模式在 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
// 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
// 在 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

注意

根据上述的说明,可以发现 Map 和 AbstractMap 其实就是一个 Component,而 HashMap 是一个 Composite,Node 是一个 Leaf。

#设计模式
上次更新: 2025/04/12, 07:54:33
装饰者模式
外观模式

← 装饰者模式 外观模式→

最近更新
01
Reactor 核心
02-24
02
前置条件
10-30
03
计算机网络
09-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式