Java设计模式之java组合模式详解

yizhihongxing

Java组合模式详解

什么是组合模式?

组合模式是一种结构型设计模式,其主要思想是将对象组合成树形结构以表示“部分整体”的层次结构。组合模式中包含两种基本的组件:

  1. 叶节点(Leaf): 叶节点代表树的最底层的节点,即无子节点的节点。
  2. 复合节点(Composite): 复合节点代表树的非叶子节点,它可能包含子节点,也可能不包含。

组合模式的优点

  • 可以更方便地扩展对象结构;
  • 对象与对象集合使用起来方便一致;
  • 简化了实现客户端代码的复杂性。

Java组合模式的实现方式

我们可以通过抽象类和接口的方式进行组合模式的实现。以员工管理为例,假设员工管理有以下两种类型的员工:

  • 普通员工(Leaf节点)
  • 经理(Composite节点)

我们可以定义一个抽象类把员工类型进行统一。该类可以是抽象类或者是接口:

abstract class Employee {
    private String name;
    private Department department;

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

    public String getName() {
        return name;
    }

    public Department getDepartment() {
        return department;
    }

    // 其他操作
    // ...

    /**
     * 添加员工
     *
     * @param employee 新增员工
     */
    public void add(Employee employee) {
        throw new UnsupportedOperationException("add");
    }

    /**
     * 删除员工
     *
     * @param employee 删除的员工
     */
    public void remove(Employee employee) {
        throw new UnsupportedOperationException("remove");
    }

    /**
     * 打印员工
     *
     * @param depth 打印深度
     */
    public abstract void print(int depth);
}

在抽象类中,我们定义了员工的名称和所属部门属性,并定义了是否是叶子节点方法和添加、删除、打印操作的抽象方法。

在这个抽象类中,并没有实现添加、删除和打印的具体操作,因为普通员工没有子员工,所以这些操作不支持对普通员工的操作。而对于经理节点,因其下面有可能包含一些子员工,因此需要重写这些方法:

class Manager extends Employee {
    private List<Employee> employees = new ArrayList<>();

    public Manager(String name, Department department) {
        super(name, department);
    }

    /**
     * 添加员工
     *
     * @param employee 新增员工
     */
    @Override
    public void add(Employee employee) {
        employees.add(employee);
    }

    /**
     * 删除员工
     *
     * @param employee 删除的员工
     */
    @Override
    public void remove(Employee employee) {
        employees.remove(employee);
    }

    /**
     * 打印员工
     *
     * @param depth 打印深度
     */
    @Override
    public void print(int depth) {
        System.out.println("depth:" + depth + ", name:" + getName());
        for (Employee employee : employees) {
            employee.print(depth + 1);
        }
    }
}

在这个实现中,Manager继承了我们定义的Employee类,并且重写了add、remove和print操作。我们可以发现,其下面定义了员工列表,这个列表中可以添加其他的Employee类型实例,也就是说,Manager可以添加其他的经理和普通员工实例。

由于普通员工没有子员工,因此它可以不重写add、remove和print方法。

组合模式的使用场景

组合模式通常需要满足以下两个条件:

  1. 应用程序需要表示部分和整体层次关系;
  2. 应用程序需要从客户端比较同一组别的对象。

例如:

  • 文件系统的目录和文件;
  • 组织结构图和员工;
  • 菜单、子菜单和菜单项等界面元素。

例子一:组织结构图和员工

我们假设一个公司有多个部门,每个部门中有多个员工,公司最高管理者是CEO。我们可以用组合模式来表达出这些关系。

Department marketing = new Department("Marketing");
Department rd = new Department("Research and Development");
Department finance = new Department("Finance");

Employee ceo = new Manager("William", marketing);
Employee cto = new Manager("Marshall", rd);
Employee cfo = new Manager("Peeters", finance);

ceo.add(cto);
ceo.add(cfo);

Employee staff1 = new Manager("Andy", marketing);
Employee staff2 = new Manager("Simon", marketing);
Employee staff3 = new Manager("Kate", rd);
Employee staff4 = new Manager("Bob", finance);

cto.add(staff1);
cto.add(staff2);
cfo.add(staff3);
cfo.add(staff4);

ceo.print(0);

执行上述代码可以得到如下输出:

depth:0, name:William
depth:1, name:Marshall
depth:2, name:Andy
depth:2, name:Simon
depth:1, name:Peeters
depth:2, name:Kate
depth:2, name:Bob

例子二:煎饼糖果店销售情况

我们假设有一个煎饼糖果店,这家店面积不大,但是它有煎饼、糖果和饮料等多种商品,我们对这些商品进行销售管理。

MenuItem pancake = new MenuItem("Pancake", "A delicious pancake with maple syrup", 2.99);
MenuItem candy = new MenuItem("Candy", "Candy with many flavors", 1.99);
MenuItem drink = new MenuItem("Drink", "Drinks and juices", 0.99);
MenuComponent menu = new Menu("Menu");

menu.add(pancake);
menu.add(candy);
menu.add(drink);

MenuComponent combo = new Menu("Combo");

MenuItem pancakeCombo = new MenuItem("Pancake Combo", "A delicious pancake with maple syrup and coffee or tea", 4.99);
MenuItem candyCombo = new MenuItem("Candy Combo", "Candy with many flavors and coffee or tea", 3.99);

combo.add(pancakeCombo);
combo.add(candyCombo);
combo.add(drink);

menu.add(combo);

menu.print();

执行上述代码可以得到如下输出:

Menu:
    Pancake A delicious pancake with maple syrup    $2.99
    Candy   Candy with many flavors $1.99
    Drink   Drinks and juices   $0.99
    Combo:
        Pancake Combo   A delicious pancake with maple syrup and coffee or tea  $4.99
        Candy Combo Candy with many flavors and coffee or tea   $3.99
        Drink   Drinks and juices   $0.99

总结

组合模式主要用于树形结构的处理,它将对象组织成树形结构,并且能够以同样的方式处理单个对象以及对象集合,从而让客户端用一致性的方式处理对象。组合模式是设计渐进式的设计策略,即它允许我们逐步地将简单的对象组合成更为复杂的对象结构。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java设计模式之java组合模式详解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • Java工厂模式优雅地创建对象以及提高代码复用率和灵活性

    Java工厂模式优雅地创建对象以及提高代码复用率和灵活性 什么是工厂模式 在面向对象编程中,将对象的创建过程和处理过程分离开来就是一种算法模式。这种算法模式就是工厂模式。简单来说,工厂模式就是将对象的创建过程进行封装和统一管理,使得代码更加灵活和便于维护和修改。工厂模式主要有两种形式:简单工厂模式和抽象工厂模式。 简单工厂模式 简单工厂模式是工厂模式中最简单…

    Java 2023年5月26日
    00
  • JavaWeb实现文件上传下载功能实例解析

    JavaWeb实现文件上传下载功能实例解析 一、文件上传 文件上传是指将本地机器上的文件通过网络传输到远程服务器上的过程。在JavaWeb中,可以使用Servlet实现文件上传功能。 在上传文件之前,需要先创建一个表单,让用户选择需要上传的文件。具体操作如下: 在HTML中创建一个表单,指定表单的enctype属性值为”multipart/form-data…

    Java 2023年5月20日
    00
  • Spring Boot整合持久层之JPA多数据源

    让我来为你详细讲解“Spring Boot整合持久层之JPA多数据源”的完整攻略。 1. 环境准备 本文假设你已经安装了以下软件: JDK 1.8或更高版本 MySQL数据库 Eclipse或IntelliJ IDEA等开发工具 此外,还需要引入以下依赖包: Spring Boot Starter Data JPA MySQL JDBC Driver(如果你…

    Java 2023年5月20日
    00
  • SSH框架网上商城项目第14战之商城首页UI的设计

    SSH框架网上商城项目第14战之商城首页UI的设计攻略 本次项目的目标是设计网上商城的首页UI界面,以下是完整攻略: 1. UI设计前期准备 在UI设计之前,为了能够更好的理解网上商城的运营模式,建议广泛了解目前热门商城的首页设计,如淘宝,京东和天猫等大型商城的首页设计,了解他们的页面布局和样式,可以借鉴他们的设计元素,同时也要挖掘出更多的特点,以创新和提高…

    Java 2023年6月15日
    00
  • Java创建随机数的四种方式总结

    Java创建随机数的四种方式总结 在Java中,有多种方式可以创建随机数。下面将总结Java创建随机数的四种方式,并给出两个示例说明。 1. java.util.Random类 使用java.util.Random类可以生成随机数。这种方式通常使用步骤如下: 创建一个Random对象,如Random rand = new Random()。 调用rand对象…

    Java 2023年5月26日
    00
  • java实现学生成绩录入系统

    Java实现学生成绩录入系统 系统功能 本系统是一个学生成绩录入系统,主要功能如下: 录入学生成绩 显示学生成绩 查询学生成绩 修改学生成绩 删除学生成绩 退出系统 系统设计 系统设计有两个部分:学生类和学生成绩类。学生类包含学生的姓名和学号等基本信息,学生成绩类包含学生的各科成绩和总分等信息。 学生类 public class Student { priv…

    Java 2023年5月24日
    00
  • FP-Growth算法的Java实现+具体实现思路+代码

    下面是“FP-Growth算法的Java实现+具体实现思路+代码”的完整攻略: FP-Growth算法简介 FP-Growth算法是一种常用的频繁项集挖掘算法,它利用了频繁项集的意义,并且能够高效地处理大规模数据集。FP-Growth算法通过将数据集压缩成一棵FP-Tree来完成频繁项集挖掘,其主要步骤包括: 构建FP-Tree; 抽取频繁项集。 FP-Gr…

    Java 2023年5月19日
    00
  • SpringBoot中打war包需要注意事项

    SpringBoot中打war包需要注意的事项 SpringBoot默认情况下是以jar包形式运行的,如果需要将SpringBoot项目部署到Web容器中,就需要将项目打成war包。下面是几个需要注意的事项: (1)修改项目的打包方式 在pom.xml文件中,将项目打包方式设置为war,并且去掉spring-boot-starter-web依赖的scope,…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部