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设计模式之(十)——组合模式的更多相关文章

  1. JAVA设计模式初探之组合模式

    先看看组合模式的定义吧:“将对象组合成树形结构以表示‘部分-整体’的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性.” 就拿剪发办卡的事情来分析一下吧. 首先,一张卡可以在总部,分店, ...

  2. Java设计模式之《组合模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6489827.html 组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是 ...

  3. C#设计模式之十组合模式(Composite)【结构型】

    一.引言   今天我们要讲[结构型]设计模式的第四个模式,该模式是[组合模式],英文名称是:Composite Pattern.当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达 ...

  4. Java设计模式学习记录-组合模式

    前言 今天要介绍的设计模式是组合模式,组合模式也是结构型设计模式的一种,它主要体现了整体与部分的关系,其典型的应用就是树形结构.组合是一组对象,其中的对象可能包含一个其他对象,也可能包含一组其他对象. ...

  5. Java设计模式之十 ---- 访问者模式和中介者模式

    前言 2018年已经过去,新的一年工作已经开始,继续总结和学习Java设计模式. 在上一篇中我们学习了行为型模式的解释器模式(Interpreter Pattern)和迭代器模式(Iterator P ...

  6. java设计模式-----13、组合模式

    Composite模式也叫组合模式,是构造型的设计模式之一.通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树. 组合(Composite)模式的其它翻译名称也很多,比如合成模式.树 ...

  7. JAVA设计模式之【组合模式】

    组合模式 用面向对象的方式来处理树形结构 组合多个对象形成树形结构以表示具有"整体-部分"关系的层次结构. 在组合模式中引入了抽象构件类Component,它是所有容器类和叶子类的 ...

  8. 《JAVA设计模式》之组合模式(Composite)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述合成(Composite)模式的: 合成模式属于对象的结构模式,有时又叫做“部分——整体”模式.合成模式将对象组织到树结构中,可以用来描述 ...

  9. java设计模式之十桥接模式(Bridge)

    桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化.桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时 ...

  10. 重学 Java 设计模式:实战组合模式(营销差异化人群发券,决策树引擎搭建场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 小朋友才做选择题,成年人我都要 头几年只要群里一问我该学哪个开发语言,哪个语言最好. ...

随机推荐

  1. 攻防世界XCTF-WEB入门全通关

    为了更好的体验,请见我的---->个人博客 XCTF的web块入门区非常简单,适合一些刚接触安全或者对网络安全常识比较了解的同学在安全搞累之余娱乐娱乐. 其主要考察下面几点: 基本的PHP.Py ...

  2. MySQL:提高笔记-5

    MySQL:提高笔记-5 学完基础的语法后,进一步对 MySQL 进行学习,前几篇为: MySQL:提高笔记-1 MySQL:提高笔记-2 MySQL:提高笔记-3 MySQL:提高笔记-4 MySQ ...

  3. Noip模拟39 2021.8.14

    T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...

  4. 2021.7.28考试总结[NOIP模拟26]

    罕见的又改完了. T1 神炎皇 吸取昨天三个出规律的教训,开场打完T2 20pts直接大力打表1h. 但怎么说呢,我不懂欧拉函数.(其实exgcd都忘了 于是只看出最大平方因子,不得不线性筛,爆拿60 ...

  5. USB线上/串口/I2C引脚串联电阻的作用

    对引脚的保护. 第一是阻抗匹配.因为信号源的阻抗很低,跟信号线之间阻抗不匹配,串上一个电阻后,可改善匹配情况,以减少反射,避免振荡等. 第二是可以减少信号边沿的陡峭程度,从而减少高频噪声以及过冲等.因 ...

  6. 用STM32内置的高速ADC实现简易示波器

    做一个数字采样示波器一直是我长久以来的愿望,不过毕竟这个目标难度比较大,涉及的方面实在太多,模拟前端电路.高速ADC.单片机.CPLD/FPGA.通讯.上位机程序.数据处理等等,不是一下子就能成的,慢 ...

  7. 转:BeanFactory和FactoryBean的区别

    一.BeanFactory简介 BeanFacotry是spring中比较原始的Factory.如XMLBeanFactory就是一种典型的BeanFactory.原始的BeanFactory无法支持 ...

  8. cat userlist(课上练习)

    问题描述 Linux文件系统的三层抽象是什么? 写出Cat userlist的过程,要详述目录文件,i-node.数据块,要画图示意. 假设块大小为4k, userlist的大小不小于10k,自己假设 ...

  9. 通过两个位置的经纬度坐标计算距离(C#版本)

    /// <summary> /// 通过地图上的两个坐标计算距离(C#版本) /// Add by 成长的小猪(Jason.Song) on 2017/11/01 /// http://b ...

  10. 测试开发【提测平台】分享13-远程搜索和路由$route使用实现新建提测需求

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 本篇继续提测平台开发,按惯例先给出学习的思维导图,以便快速了解学习知识和平台功能实现的重点. 基本知识点学习 远程搜索 显示的数据通过输入 ...