笨蛋学设计模式结构型模式-组合模式【12】

结构型模式-组合模式

7.6组合模式

7.6.1概念

​ 组合模式通过将对象组合成树状结构来表示 部分-整体的层次关系,从而让客户端能够以同样的方式处理单个对象和对象组合,在使用中将他们视为同一类型的对象。

7.6.2场景

​ 在文件系统中,比如目录和文件就形成了一个树形结构,目录可以包含文件以及子目录,而子目录同样的也可以包含文件以及子目录的子目录。

7.6.3优势 / 劣势

  • 一致性:客户端可以统一的处理单个对象和对象的组合,简化了客户端的代码
  • 动态性:组合模式支持动态地添加或删除子对象,使得树形结构的构建更加灵活

  • 复杂性:由于树形机构的嵌套特性,可能会增加代码的复杂性
  • 深度限制:若组合模式的树形结构的深度过大,可能会导致性能问题

7.6.4组合模式可分为

  • 组件Component:组合模式的根节点,定义组合中所有对象的通用接口,可以是抽象类或接口。该类中定义了子类的共性内容
  • 叶子Leaf:实现了Component接口的叶子节点,表示组合中的叶子对象,叶子节点没有子节点
  • 合成Composite:作用是存储子部件,并且在Composite中实现了对子部件的相关操作,比如添加、删除、获取子组件等

7.6.5组合模式

java 复制代码
package com.technologystatck.designpattern.mode.combination;

import java.util.ArrayList;
import java.util.List;

public class Combination {
    public static void main(String[] args) {
        //创建叶子节点
        Leaf leaf = new Leaf();

        //创建组合节点,并添加叶子节点
        Composite composite = new Composite();
        composite.add(leaf);

        //统一调用
        composite.operation();

        System.out.println("----------------------");
        composite.remove(leaf);
        composite.operation();
    }
}

//组件接口
interface Component{
    void operation();
}

//叶子节点
class Leaf implements Component{

    @Override
    public void operation() {
        System.out.println("Leaf operation");
    }
}

//组合节点
class Composite implements Component{
    private List<Component> components=new ArrayList<>();

    public void add(Component component){
        components.add(component);
    }

    public void remove(Component component){
        components.remove(component);
    }

    @Override
    public void operation() {
        System.out.println("Composite operation");
        for(Component component:components){
            component.operation();
        }
    }
}

7.6.6实战

7.6.6.1题目描述

小明所在的公司内部有多个部门,每个部门下可能有不同的子部门或者员工。

请你设计一个组合模式来管理这些部门和员工,实现对公司组织结构的统一操作。部门和员工都具有一个通用的接口,可以获取他们的名称以及展示公司组织结构。

7.6.6.2输入描述

第一行是一个整数 N(1 <= N <= 100),表示后面有 N 行输入。

接下来的 N 行,每行描述一个部门或员工的信息。部门的信息格式为 D 部门名称,员工的信息格式为 E 员工名称,其中 D 或 E 表示部门或员工。

7.6.6.3输出描述

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

7.6.6.4代码
java 复制代码
package com.technologystatck.designpattern.mode.combination;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //先读取公司名称
        String companyName = scanner.nextLine();

        //创建公司对象,并设置公司名称,并将公司添加到树枝节点中
        Company company = new Company(companyName);


        //读取部门和员工信息
        int nums = scanner.nextInt();
        scanner.nextLine();
        for(int i=0;i<nums;i++){
            String type = scanner.next();
            //获取名字并去除空格,以便后续添加到组合节点中
            String name = scanner.nextLine().trim();

            if("D".equals(type)){
                //创建部门对象,并添加到组合节点中
                company.add(new Department(name));
            }else if("E".equals(type)){
                //创建员工对象,并添加到组合节点中
                company.add(new Employee(name));
            }
        }
        //显示公司信息
        company.display();

    }
}

//组件接口
interface Components{
    void display(int depth);
}

//部门的叶子节点
class Department implements Components{

    //部门名称
    private String name;
    //部门下的员工
    private List<Components> children;

    public Department(String name) {
        this.name = name;
        this.children = new ArrayList<>();
    }

    //添加员工
    public void add(Components component){
        children.add(component);
    }
    //删除员工
    public void remove(Components component){
        children.remove(component);
    }
    @Override
    public void display(int depth) {
        StringBuilder indent = new StringBuilder();
        for(int i = 0;i < depth;i++){
            //一个空格
            indent.append(" ");
        }
        System.out.println(indent + name);
        for (Components components : children) {
            components.display(depth+1);
        }
    }
}

//员工的叶子节点
class Employee implements Components{
    //员工名
    private String name;

    public Employee(String name) {
        this.name = name;
    }

    @Override
    public void display(int depth) {
        StringBuilder indent = new StringBuilder();
        for(int i = 0;i < depth;i++){
            //两个空格,用于缩进显示层级关系
            indent.append("  ");
        }
        System.out.println(indent + name);
    }
}

//树枝节点,也就是组合节点
class Company{
    private String name;
    //部门相当于根节点
    private Department root;

    public Company(String name) {
        this.name = name;
        this.root = new Department(name);
    }

    public void add(Components components){
        root.add(components);
    }
    public void remove(Components components){
        root.remove(components);
    }

    public void display(){
        System.out.println("Company Structure");
        //从1开始,以适配指定的缩进格式
        root.display(0);
    }
}

7.6.7总结

组合模式

  • 优点:可以通过组合多个对象形成对象组合,然后再增加新的功能或行为,只需要对组合对象进行操作

  • 总结:是一种通过将对象组合成树形结构,提供了灵活且统一的方式来处理单个对象和对象组合

  • 场景:需要构建具有部分-整体层次结构的场景,比如组织架构管理、文件系统的文件和文件夹组织

相关推荐
向哆哆几秒前
Java与NoSQL数据库的集成与优化
java·开发语言·nosql
茂茂在长安3 分钟前
Linux 命令大全完整版(11)
java·linux·运维·服务器·前端·centos
songbaoxian15 分钟前
ElasticSearch
java·linux·elasticsearch
非 白30 分钟前
【Java】代理模式
java·开发语言·代理模式
Good Note40 分钟前
Golang的静态强类型、编译型、并发型
java·数据库·redis·后端·mysql·面试·golang
我就是我3521 小时前
记录一次SpringMVC的406错误
java·后端·springmvc
向哆哆1 小时前
Java应用程序的跨平台性能优化研究
java·开发语言·性能优化
ekkcole2 小时前
windows使用命令解压jar包,替换里面的文件。并重新打包成jar包,解决Failed to get nested archive for entry
java·windows·jar
handsomestWei2 小时前
java实现多图合成mp4和视频附件下载
java·开发语言·音视频·wutool·图片合成视频·视频附件下载
全栈若城3 小时前
03 Python字符串与基础操作详解
java·开发语言·python