对组合模式的理解

目录

  • 一、场景
    • 1、题目描述 【[案例来源](https://kamacoder.com/problempage.php?pid=1090)】
    • 2、输入描述
    • 3、输出描述
    • 4、输入示例
    • 5、输出示例
  • 二、实现(假的组合模式)
    • 1、代码
    • 2、为什么上面的写法是假的组合模式?
  • 三、实现(真的组合模式)
    • 1、案例来源的实现
    • 2、我的实现
  • 四、个人思考

一、场景

设计模式很依赖场景,通过场景也能更好理解这种模式解决了什么问题。

  • 无论是学校还是公司,都存在组织结构。而且,这种结构多半是树状结构。
  • 当类与类之间的结构也需要表达成树状结构时,组合模式就来大显身手了。

1、题目描述 【案例来源】

小明所在的公司内部有多个部门,每个部门下可能有不同的子部门或者员工。
请你设计一个组合模式来管理这些部门和员工,实现对公司组织结构的统一操作。部门和员工都具有一个通用的接口,可以获取他们的名称以及展示公司组织结构。

2、输入描述

第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。
接下来的 N 行,每行描述一个部门或员工的信息。部门的信息格式为 D 部门名称,员工的信息格式为 E 员工名称,其中 D 或 E 表示部门或员工。

3、输出描述

输出公司的组织结构,展示每个部门下的子部门和员工

4、输入示例

MyCompany
8
D HR
E HRManager
D Finance
E AccountantA
E AccountantB
D IT
E DeveloperA
E DeveloperB

5、输出示例

Company Structure:
MyCompany
HR
HRManager
Finance
AccountantA
AccountantB
IT
DeveloperA
DeveloperB

二、实现(假的组合模式)

1、代码

public interface Component {String showName();
}public class Company implements Component {private final String name;@Setterprivate List<Department> departments;public Company(String name) {this.name = name;}public void addDepartment(Department department) {if (CollectionUtils.isEmpty(departments)) {departments = new ArrayList<>();departments.add(department);} else {departments.add(department);}}@Nullablepublic Department gotLastDepartment() {if (CollectionUtils.isEmpty(departments)) {return null;} else {return departments.get(departments.size() - 1);}}@Overridepublic String showName() {return name;}public String showCompanyStructure() {StringBuilder sb = new StringBuilder("Company Structure:\n").append(showName()).append("\n");Optional.ofNullable(departments).ifPresent(departments -> departments.stream().filter(Objects::nonNull).forEach(department -> {sb.append("  ").append(department.showName()).append("\n");Optional.ofNullable(department.getEmployees()).ifPresent(employees -> {employees.stream().forEach(employee -> sb.append("    ").append(employee.showName()).append("\n"));});}));return sb.toString();}
}@Data
public class Department implements Component {private String name;private List<Employee> employees;public Department(String name) {this.name = name;}@Overridepublic String showName() {return this.name;}public void addEmployee(Employee employee) {if (CollectionUtils.isEmpty(employees)) {employees = new ArrayList<>();employees.add(employee);} else {employees.add(employee);}}
}@AllArgsConstructor
public class Employee implements Component {private String name;@Overridepublic String showName() {return name;}
}
public class Application {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String companyName = scanner.nextLine();Company company = new Company(companyName);int n = scanner.nextInt();for (int i = 0; i < n; i++) {String type = scanner.next();String name = scanner.next();if (StringUtils.equals(type, "D")) {company.addDepartment(new Department(name));} else if (StringUtils.equals(type, "E")) {Department department = company.gotLastDepartment();department.addEmployee(new Employee(name));}}System.out.printf(company.showCompanyStructure());}
}

2、为什么上面的写法是假的组合模式?

  • 场景中的公司结构:
    在这里插入图片描述
    • 对这个结构进行建模,不应该是:
public class Company implements Component {private final String name;@Setterprivate List<Department> departments;
}public class Department implements Component {private String name;private List<Employee> employees;
}public class Employee implements Component {private String name;
}
  • 因为上图实际上有2个基本结构:
// Company-Department (1 对 n)、Department-Employee(1对n)
class Composite implements Component {private String name;private List<Component> children;
}// 这个便是Employee
class Leaf implements Component {private String name;
}
  • 所以,没有Get到这一点,就容易写出假的组合模式。(写的时候也会发现写的很累)

三、实现(真的组合模式)

1、案例来源的实现

  • 场景中题目的提供方,也给出了相应的实现:
public interface Component {void display(int depth);
}public class Department implements Component {private String name;private List<Component> children;public Department(String name) {this.name = name;this.children = new ArrayList<>();}public void add(Component component) {children.add(component);}@Overridepublic void display(int depth) {StringBuilder indent = new StringBuilder();for (int i = 0; i < depth; i++) {indent.append("  ");}System.out.println(indent + name);for (Component component : children) {component.display(depth + 1);}}
}public class Employee implements Component {private String name;public Employee(String name) {this.name = name;}@Overridepublic void display(int depth) {StringBuilder indent = new StringBuilder();for (int i = 0; i < depth; i++) {indent.append("  ");}System.out.println(indent + "  " + name);}
}public class Company {private String name;private Department root;public Company(String name) {this.name = name;this.root = new Department(name);}public void add(Component component) {root.add(component);}public void display() {System.out.println("Company Structure:");root.display(0); // 从 1 开始,以适配指定的缩进格式}public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);
// 读取公司名称String companyName = scanner.nextLine();Company company = new Company(companyName);
// 读取部⻔和员工数量int n = scanner.nextInt();scanner.nextLine(); // 消耗换行符
// 读取部⻔和员工信息for (int i = 0; i < n; i++) {String type = scanner.next();String name = scanner.nextLine().trim();if ("D".equals(type)) {Department department = new Department(name);company.add(department);} else if ("E".equals(type)) {Employee employee = new Employee(name);company.add(employee);}}
// 输出公司组织结构company.display();}
}
  • debug会发现,这并没有正确表示company的结构:
    在这里插入图片描述
  • 那为啥能输出这样的结果呢?
MyCompanyHRHRManagerFinanceAccountantAAccountantBITDeveloperADeveloperB
  • 原因在于:
public class Employee implements Component {...@Overridepublic void display(int depth) {StringBuilder indent = new StringBuilder();for (int i = 0; i < depth; i++) {indent.append("  ");}System.out.println(indent + "  " + name); // 这里的depth实际上是1,因此作者多加了"  "}
}

显然,这并不是正确的实现。

2、我的实现

public interface Component {void showName(int depth);
}public class Composite implements Component {private String name;private List<Component> children;public Composite(String name) {this.name = name;children = new ArrayList<>();}public void addComponent(Component component) {children.add(component);}public Composite gotLastComposite() {if (!children.isEmpty()) {Component component = children.get(children.size() - 1);if (component instanceof Composite) {return (Composite) component;} else {throw new RuntimeException("last component is not composite");}} else {throw new RuntimeException("doesn't exist last component");}}@Overridepublic void showName(int depth) {System.out.println(StringUtils.repeat("  ", depth) + name);for (Component child : children) {child.showName(depth + 1);}}
}@AllArgsConstructor
public class Employee implements Component {private String name;@Overridepublic void showName(int depth) {System.out.println(StringUtils.repeat("  ", depth) + name);}
}public class Company extends Composite {public Company(String name) {super(name);}@Overridepublic void showName(int depth) {System.out.println("Company Structure:");super.showName(depth);}
}
public class Application {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String companyName = scanner.nextLine();Company company = new Company(companyName);int n = scanner.nextInt();for (int i = 0; i < n; i++) {String type = scanner.next();String name = scanner.next();if (StringUtils.equals(type, "D")) {company.addComponent(new Composite(name));} else if (StringUtils.equals(type, "E")) {Composite department = company.gotLastComposite();department.addComponent(new Employee(name));}}company.showName(0);}
}
  • Company的结构:
    在这里插入图片描述

四、个人思考

  • 对真实场景建模后,类呈现树状结构,那么可以尝试使用组合模式设计代码:
class Composite implements Component {private String name;private List<Component> children;
}// 这个便是Employee
class Leaf implements Component {private String name;
}

组合模式:实现接口A + 组合多个接口A

  • 装饰模式、桥接模式都用到了组合的理念,但都是一对一的形式:
  • 装饰模式:实现接口A + 组合接口A
public class EncryptDataSourceImpl implements DataSource {private DataSource dataSource;
}
  • 桥接模式:实现接口A + 组合接口B
public class Circle implements Shape {private Color color;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本生成任务的评价方法BLEU 和 ROUGE

BLEU 是 2002 年提出的&#xff0c;而 ROUGE 是 2003 年提出的。这两种指标虽然存在着一些问题&#xff0c;但是仍然是比较主流的评价指标。 BLUE BLEU 的全称是 Bilingual evaluation understudy&#xff0c;BLEU 的分数取值范围是 0&#xff5e;1&#xff0c;分数越接近1&a…

使用new 关键字调用函数,创建对象的过程中做了什么

使用new 关键字调用函数&#xff0c;创建对象的过程中做了什么 使用 new关键字创建对象的过程大致可以分为以下几个步骤&#xff1a; 创建空对象&#xff1a;首先&#xff0c;new操作符会创建一个空对象&#xff0c;这个对象的隐式原型__proto__属性会被设置为构造函数的显示原…

YOLOv9改进策略 | 细节创新篇 | 迭代注意力特征融合AFF机制创新RepNCSPELAN4

一、本文介绍 本文给大家带来的改进机制是AFF&#xff08;迭代注意力特征融合&#xff09;&#xff0c;其主要思想是通过改善特征融合过程来提高检测精度。传统的特征融合方法如加法或串联简单&#xff0c;未考虑到特定对象的融合适用性。iAFF通过引入多尺度通道注意力模块(我…

搭建vue3组件库(一):Monorepo项目搭建

Monorepo Monorepo 是一种项目代码管理方式&#xff0c;指单个仓库中管理多个项目&#xff0c;有助于简化代码共享、版本控制、构建和部署等方面的复杂性&#xff0c;并提供更好的可重用性和协作性。 pnpm pnpm 全称 performant npm&#xff0c;意思为 高性能的 npm。pnpm 由…

mysql面试题六(视图,存储过程,触发器)

目录 1.什么是视图 视图的特点 视图的创建与使用 视图的用途与优势 注意事项 2.什么是存储过程 存储过程的特点 存储过程的创建与调用 存储过程的使用场景 注意事项 3.什么是触发器 触发器的特点 触发器的创建与管理 触发器的使用场景 注意事项 1.什么是视图 在…

算法打卡day52|单调栈篇03| 84.柱状图中最大的矩形

算法题 Leetcode 84.柱状图中最大的矩形 题目链接:84.柱状图中最大的矩形 大佬视频讲解&#xff1a;84.柱状图中最大的矩形视频讲解 个人思路 这题和接雨水是相似的题目&#xff0c;原理上基本相同&#xff0c;也是可以用双指针和单调栈解决&#xff0c;只是有些细节不同。…

深度学习之目标检测从入门到精通——json转yolo格式

记录点&#xff1a; import json import osname2id {person:0,helmet:1,Fire extinguisher:2,Hook:3,Gas cylinder:4}def convert(img_size, box):dw 1./(img_size[0])dh 1./(img_size[1])x (box[0] box[2])/2.0 - 1y (box[1] box[3])/2.0 - 1w box[2] - box[0]h box…

23种设计模式之行为模式篇

三、行为模式 这类模式主要关注对象之间的通信&#xff0c;尤其是它们之间进行通信的方式和时机。 包括&#xff1a; 策略模式&#xff08;Strategy&#xff09;模板方法模式&#xff08;Template Method&#xff09;观察者模式&#xff08;Observer&#xff09;迭代器模式&…

jtop安装

一、安装依赖环境 sudo apt-get install git cmake sudo apt-get install python3-dev sudo apt-get install libhdf5-serial-dev hdf5-tools sudo apt-get install libatlas-base-dev gfortran二、pip3安装 sudo apt-get update sudo apt-get upgrade sudo apt-get install …

「High Cry」Solution

简述题意 给定长度为 n n n 的数组 n n n&#xff0c;求出有多少个区间满足区间或大于区间最大值。 n ≤ 2 1 0 5 n \le 2 \times 10^5 n≤2105 思路 从区间入手肯定不好做&#xff0c;考虑从最大值入手。 注意到一个区间&#xff0c;其肯定有一个最大值 a i a_i ai​&…

【rust简单工具理解】

1.map方法 map这个闭包的本质就是映射 let numbers vec![1, 2, 3, 4, 5]; let numbers_f64: Vec<f64> numbers.into_iter().map(|&x| x as f64).collect(); println!("{:?}", numbers_f64); // 输出: [1.0, 2.0, 3.0, 4.0, 5.0]2.and_then and_then …

锦瑟香也MYLOVE:音质与颜值俱佳,入坑HiFi的热门好物!

当下尽管无线耳机大行其道&#xff0c;但有线耳机依旧保有其独特的魅力&#xff0c;特别是在音质表现上&#xff0c;它们拥有无线耳机难以企及的优势。如果对音质要求很高的话&#xff0c;口袋里还是少不了一副有线耳机。国产品牌中就有许多性价比高的有线耳机&#xff0c;它们…

Django admin后台添加自定义菜单和功能页面

django admin是根据注册的模型来动态生成菜单&#xff0c;从这个思路出发&#xff0c;如果想添加自定义菜单&#xff0c;那就创建一个空模型并且注册。步骤如下&#xff1a; 1、创建空模型&#xff1a; class ResetSVNAuthFileModel(models.Model):"""仅用来显…

学习 Rust 的第五天:了解程序的基本控制流程

大家好呀 欢迎来到这个学习 Rust 的 30 天系列的第五天&#xff0c;今天我们将深入了解 Rust 中的控制流。 控制流&#xff0c;顾名思义&#xff0c;根据条件来 控制程序的流程。 If 表达式 当你想要在满足条件时执行一段代码块时&#xff0c;可以使用 if 表达式。 示例 …

菜鸟Java基础教程 9.Java 循环结构

Java 循环结构 - for, while 及 do…while Java循环结构 Java 循环结构 - for, while 及 do...while1. while 循环实例Test.java 文件代码&#xff1a; 2. do…while 循环实例Test.java 文件代码&#xff1a; 3. for循环实例Test.java 文件代码&#xff1a; 4. Java 增强 for 循…

数据类型判断的方法

一、typeof 使用方法如下&#xff1a; typeof operand typeof(operand)operand表示要返回类型的对象或基本类型的表达式 &#xff0c;typeof运算符返回一个字符串&#xff0c;表示操作数的类型。 typeof 666 // number typeof 666 // string typeof undefined // undefined …

《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制伊甸火山3D网格曲面图

11.4.2小节我们使用3D曲面图可视化分析伊甸火山数据&#xff0c;本小节我们采用3D网格曲面图可视化分析伊甸火山数据&#xff0c;以展示其地形&#xff0c;具体示例代码如下。 购书地址&#xff1a;https://item.jd.com/14102657.html

Django数据导出与导入问题

执行: python manage.py loaddata data.json 的常见错误: * 1. UnicodeDecodeError: utf-8 codec cant decode byte 0xff in position 0: invalid start byte* 2. raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",...django.core.serializer…

css animation 动画详细学习

学习 CSS 动画是一个深入且富有创造性的过程&#xff0c;它允许开发者创建出引人入胜且交互性强的网页效果。以下是对 CSS 动画学习的一些总结和要点&#xff1a; 1. 关键帧动画&#xff08;keyframes&#xff09; 使用 keyframes 规则定义动画的整个过程。在 keyframes 中&a…

聚道云软件连接器助力企业实现滴滴出差报销自动化

一、客户介绍 某机械有限公司是一家在机械设备制造领域拥有深厚底蕴和卓越实力的企业。自公司成立以来&#xff0c;该公司始终秉承创新、务实、高效的发展理念&#xff0c;专注于机械设备的研发、生产和销售。经过多年的发展&#xff0c;公司已成为国内机械行业的佼佼者&#…