Java设计模式之(十)——组合模式
1、什么是组合模式?
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构, 使得用户对单个对象和组合对象的使用具有一致性。
说人话:用于处理树形结构数据。
2、组合模式定义

①、Component 抽象构件角色
定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性。
②、Leaf 叶子节点
叶子对象,其下再也没有其他的子节点,是遍历的最小单位。
③、Composite 树枝构件
树枝对象,作用是组合树枝节点和叶子节点形成一个树形结构。
3、组合模式通用代码实现
/**
* 个体和整体的抽象
*/
public abstract class Component {
// 个体和整体都有的共享
public void doSomething(){
// 通用业务逻辑
System.out.println("通用业务逻辑");
}
}
/**
* 树枝节点
*/
public class Composite extends Component{
// 构件容器
private ArrayList<Component> componentArrayList = new ArrayList<>();
// 增加一个叶子节点或者树枝节点
public void add(Component component){
this.componentArrayList.add(component);
}
// 删除一个叶子节点或者树枝节点
public void remove(Component component){
this.componentArrayList.remove(component);
}
// 获取分支下所有叶子节点和树枝节点
public List<Component> getChildren(){
return this.componentArrayList;
}
}
/**
* 叶子节点
*/
public class Leaf extends Component {
// 覆写父类方法
@Override
public void doSomething() {
// 叶子节点逻辑
System.out.println("叶子节点逻辑");
}
}
测试:
public class ClientTest {
public static void main(String[] args) {
// 创建一个根节点
Composite root = new Composite();
root.doSomething();
// 创建一个树枝构件
Composite branch = new Composite();
// 创建一个叶子节点
Leaf leaf = new Leaf();
// 串联起来
root.add(branch);
branch.add(leaf);
display(root);
}
// 通过递归遍历数
public static void display(Composite root){
for(Component c : root.getChildren()){
if(c instanceof Leaf){ // 叶子节点
c.doSomething();
}else{
display((Composite) c);
}
}
}
}
这里我们在举一个例子:
假设我们在开发一个 OA 系统(办公自动化系统)。公司的组织结构包含部门和员工两种数据类型。其中,部门又可以包含子部门和员工。
我们希望在内存中构建整个公司的人员架构图(部门、子部门、员工的隶属关系),并且提供接口计算出部门的薪资成本(隶属于这个部门的所有员工的薪资和)。

/**
* 部门类和员工类的抽象类
*/
public abstract class HumanResource {
protected long id;
protected double salary;
public HumanResource(long id){
this.id = id;
}
public long getId(){
return id;
}
public abstract double calculateSalary();
}
public class Department extends HumanResource{
private List<HumanResource> subNodes = new ArrayList<>();
public Department(long id){
super(id);
}
@Override
public double calculateSalary() {
double totalSalary = 0d;
for (HumanResource hr : subNodes){
totalSalary += hr.calculateSalary();
}
this.salary = totalSalary;
return totalSalary;
}
public void addSubNode(HumanResource humanResource){
subNodes.add(humanResource);
}
}
public class Employee extends HumanResource{
public Employee(long id,double salary){
super(id);
this.salary = salary;
}
@Override
public double calculateSalary() {
return salary;
}
}
测试:
public class PersonClientTest {
private static final long ORGANIZATION_ROOT_ID = 1;
public static void main(String[] args) {
// 创建总部门
Department root = new Department(ORGANIZATION_ROOT_ID);
// 创建子部门
Department branch = new Department(2L);
// 创建员工
Employee employee1 = new Employee(21L,2000);
Employee employee2 = new Employee(22L,4000);
root.addSubNode(branch);
branch.addSubNode(employee1);
branch.addSubNode(employee2);
double v = root.calculateSalary();
System.out.println(v);
}
private void buildOrganization(Department department){
// 根据 部门id 查询数据库 所有下属部门 id
// List<Long> subDepartmentIds = departmentRepo.getSubDepartmentIds(department.getId());
List<Long> subDepartmentIds = new ArrayList<>();
for (Long subDepartmentId : subDepartmentIds){
Department subDepartment = new Department(subDepartmentId);
department.addSubNode(subDepartment);
buildOrganization(subDepartment);
}
// 根据部门id 查询数据库 其关联员工所有 id
// List<Long> employeeIds = employeeRepo.getDepartmentEmployeeIds(department.getId());
List<Long> employeeIds = new ArrayList<>();
for (Long employeeId : employeeIds){
// 根据 employeeId 查询数据库得到 salary
// 假设为 1000
double salary = 1000d;
department.addSubNode(new Employee(employeeId,salary));
}
}
}
4、组合模式优点
①、高层模块调用简单
一棵树形机构中的所有节点都是Component, 局部和整体对调用者来说没有任何区别,也就是说, 高层模块不必关心自己处理的是单个对象还是整个组合结构, 简化了高层模块的代码。
②、节点自由增加
使用了组合模式后, 如果想增加一个树枝节点、 叶子节点都很容易, 只要找到它的父节点就成, 非常容易扩展, 符合开闭原则, 对以后的维护非常有利。
5、组合模式应用场景
只要是树形结构,就可以考虑使用组合模式。
①、维护和展示部分-整体关系的场景, 如树形菜单、 文件和文件夹管理。
②、从一个整体中能够独立出部分模块或功能的场景
Java设计模式之(十)——组合模式的更多相关文章
- JAVA设计模式初探之组合模式
先看看组合模式的定义吧:“将对象组合成树形结构以表示‘部分-整体’的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性.” 就拿剪发办卡的事情来分析一下吧. 首先,一张卡可以在总部,分店, ...
- Java设计模式之《组合模式》及应用场景
摘要: 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6489827.html 组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是 ...
- C#设计模式之十组合模式(Composite)【结构型】
一.引言 今天我们要讲[结构型]设计模式的第四个模式,该模式是[组合模式],英文名称是:Composite Pattern.当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达 ...
- Java设计模式学习记录-组合模式
前言 今天要介绍的设计模式是组合模式,组合模式也是结构型设计模式的一种,它主要体现了整体与部分的关系,其典型的应用就是树形结构.组合是一组对象,其中的对象可能包含一个其他对象,也可能包含一组其他对象. ...
- Java设计模式之十 ---- 访问者模式和中介者模式
前言 2018年已经过去,新的一年工作已经开始,继续总结和学习Java设计模式. 在上一篇中我们学习了行为型模式的解释器模式(Interpreter Pattern)和迭代器模式(Iterator P ...
- java设计模式-----13、组合模式
Composite模式也叫组合模式,是构造型的设计模式之一.通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树. 组合(Composite)模式的其它翻译名称也很多,比如合成模式.树 ...
- JAVA设计模式之【组合模式】
组合模式 用面向对象的方式来处理树形结构 组合多个对象形成树形结构以表示具有"整体-部分"关系的层次结构. 在组合模式中引入了抽象构件类Component,它是所有容器类和叶子类的 ...
- 《JAVA设计模式》之组合模式(Composite)
在阎宏博士的<JAVA与模式>一书中开头是这样描述合成(Composite)模式的: 合成模式属于对象的结构模式,有时又叫做“部分——整体”模式.合成模式将对象组织到树结构中,可以用来描述 ...
- java设计模式之十桥接模式(Bridge)
桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化.桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时 ...
- 重学 Java 设计模式:实战组合模式(营销差异化人群发券,决策树引擎搭建场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 小朋友才做选择题,成年人我都要 头几年只要群里一问我该学哪个开发语言,哪个语言最好. ...
随机推荐
- 分布式事物SAGA
目录 概述SAGA SAGA的执行方式 存在的问题 重试机制 SAGA VS TCC 实现SAGA的框架 概述SAGA SAGA是1987 Hector & Kenneth 发表的论文,主要是 ...
- 【数据结构与算法Python版学习笔记】图——最短路径问题、最小生成树
最短路径问题 概念 可以通过"traceroute"命令来跟踪信息传送的路径: traceroute www.lib.pku.edu.cn 可以将互联网路由器体系表示为一个带权边的 ...
- vue3.x异步组件
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块 vue2.x 曾经简单的异步组件 components: { AsyncComponent: () =& ...
- 欧姆龙PLC HostLink协议整理
欧姆龙PLC HostLink协议整理 1.常用的存储器功能区 CIO: 输入继电器 272 点(17 CH) 0.00-16.15 输出继电器 272 点(17 CH) 100.00-116.1 ...
- [源码解析] Pytorch 如何实现后向传播 (2)---- 引擎静态结构
[源码解析] Pytorch 如何实现后向传播 (2)---- 引擎静态结构 目录 [源码解析] Pytorch 如何实现后向传播 (2)---- 引擎静态结构 0x00 摘要 0x01 Engine ...
- Seata整合SpringBoot和Mybatis
Seata整合SpringBoot和Mybatis 一.背景 二.实现功能 三.每个服务使用到的技术 1.账户服务 2.订单服务 四.服务实现 1.账户服务实现 1.引入jar包 2.项目配置 3.建 ...
- 联赛膜你测试20 T1 Simple 题解 && NOIP2017 小凯的疑惑 题解(赛瓦维斯特定理)
前言: 数学题,对于我这种菜B还是需要多磨啊 Simple 首先它问不是好数的数量,可以转化为用总数量减去是好数的数量. 求"好数"的数量: 由裴蜀定理得,如果某个数\(i\)不能 ...
- 2021.8.15考试总结[NOIP模拟40]
T1 送花 线段树.枚举右端点,线段树记录左端点对应的值. 每次对当前颜色上上次出现的位置到上次出现的位置区间减,上次出现的位置到当前位置区间加. $code:$ 1 #include<bits ...
- 虚树 virtual-tree
我们发现,如果一棵树中真正需要处理的点很少,而总共点数很多时,可以只处理那些需要的点,而忽略其他点. 因此我们可以根据那些需要的点构建虚树,只保留关键点. oi-wiki上对虚树的介绍 我们根据一下方 ...
- hdu 5101 Select (二分+单调)
题意: 多多有一个智商值K. 有n个班级,第i个班级有mi个人.智商分别是v1,v2,.....vm. 多多要从这些人中选出两人.要求两人智商和大于K,并且两人不同班.问总共有多少种方案. 数据范围: ...