java实现Composite组合模式的实例代码

下面我将为你讲解Java实现Composite组合模式的实例代码完整攻略。在完成该过程前,我先将Composite组合模式的一些基本概念进行简单介绍。

Composite组合模式是一种结构化设计模式,用于将对象组合成树状结构,以表示“部分-整体”的层次关系。该模式使得客户端能够使用统一的接口处理单个对象以及对象组合,从而将单个对象与组合对象视为等同的对象。

接下来,我们来看一下Composite组合模式的实现步骤及其代码示例。

1. 定义组合模式接口及其实现类

首先,我们需要定义组合接口,其包括添加和删除节点,获取节点以及执行操作等方法。

public interface Component {
    void add(Component component);
    void remove(Component component);
    Component getChild(int index);
    void operation();
}

然后,我们再定义其实现类,包括叶节点和组合节点。

public class Leaf implements Component{
    @Override
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Component getChild(int index) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void operation() {
        System.out.println("执行叶节点操作");
    }
}

public class Composite implements Component {
    private List<Component> components = new ArrayList<>();

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

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

    @Override
    public Component getChild(int index) {
        return components.get(index);
    }

    @Override
    public void operation() {
        System.out.println("执行组合节点操作");
        for(Component component : components) {
            component.operation();
        }
    }
}

2. 将对象组合成树状结构

接下来,我们可以通过将对象组合成树状结构来完成整体与部分间的层次关系。

Composite root = new Composite();
Composite component1 = new Composite();
Composite component2 = new Composite();
Leaf leaf1 = new Leaf();
Leaf leaf2 = new Leaf();

root.add(component1);
root.add(component2);
component1.add(leaf1);
component2.add(leaf2);

如上代码便构建了一棵树,root节点下包含component1和component2两个组合节点,而component1节点下又包含一个叶节点leaf1,component2包含一个叶节点leaf2。

3. 使用组合模式实现操作

利用Composite组合模式,我们可以使用相同的方式来操作单个对象和组合对象。

root.operation();

通过以上代码的执行,我们便可依次调用根节点以及其子节点的操作方法,从而实现对整棵树的操作。

示例说明

示例1. 文件系统演示

考虑一个应用场景,文件系统中的目录与文件可以使用Composite模式进行设计。目录可包含多个子目录或文件,而文件则为叶节点,无法再添加子节点。

public class Directory implements Component {
    private String name;
    private List<Component> children = new ArrayList<>();

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

    @Override
    public void add(Component component) {
        children.add(component);
    }

    @Override
    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public Component getChild(int index) {
        return children.get(index);
    }

    @Override
    public void operation() {
        System.out.println("当前目录为:" + name);
        for(Component component : children) {
            component.operation();
        }
    }
}

public class File implements Component {
    private String name;

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

    @Override
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Component getChild(int index) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void operation() {
        System.out.println("当前文件为:" + name);
    }
}

创建一个文件系统并操作:

Directory root = new Directory("/");
Directory usr = new Directory("usr");
Directory opt = new Directory("opt");
File config = new File("config.txt");
File profile = new File("profile.txt");

root.add(usr);
root.add(opt);
usr.add(config);
opt.add(profile);

root.operation();

输出结果:

当前目录为:/
当前目录为:usr
当前文件为:config.txt
当前目录为:opt
当前文件为:profile.txt

示例2. 餐厅菜单演示

考虑一个应用场景,餐厅菜单的设计中可包含多个子菜单或菜品,每个菜品为叶节点,无法再添加子节点。

public abstract class MenuComponent {

    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    public void remove(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    public MenuComponent getChild(int index) {
        throw new UnsupportedOperationException();
    }

    public abstract String getName();
    public abstract String getDescription();
    public abstract double getPrice();
    public abstract boolean isVegetarian();
    public abstract void print();
}

public class MenuItem extends MenuComponent {
    private String name;
    private String description;
    private boolean vegetarian;
    private double price;

    public MenuItem(String name, String description, boolean vegetarian, double price) {
        this.name = name;
        this.description = description;
        this.vegetarian = vegetarian;
        this.price = price;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public double getPrice() {
        return price;
    }

    @Override
    public boolean isVegetarian() {
        return vegetarian;
    }

    @Override
    public void print() {
        System.out.print("  " + getName());
        if (isVegetarian()) {
            System.out.print("(v)");
        }
        System.out.println(", " + getPrice());
        System.out.println("     -- " + getDescription());
    }
}

public class Menu extends MenuComponent {
    private List<MenuComponent> menuComponents = new ArrayList<>();
    private String name;
    private String description;

    public Menu(String name, String description) {
        this.name = name;
        this.description = description;
    }

    @Override
    public void add(MenuComponent menuComponent) {
        menuComponents.add(menuComponent);
    }

    @Override
    public void remove(MenuComponent menuComponent) {
        menuComponents.remove(menuComponent);
    }

    @Override
    public MenuComponent getChild(int index) {
        return menuComponents.get(index);
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    @Override
    public void print() {
        System.out.print("\n" + getName());
        System.out.println(", " + getDescription());
        System.out.println("---------------------------");

        for (MenuComponent menuComponent : menuComponents) {
            menuComponent.print();
        }
    }
}

创建一个菜单并操作:

MenuComponent breakfastMenu = new Menu("Breakfast Menu", "All Day Breakfast");
MenuComponent lunchMenu = new Menu("Lunch Menu", "Delicious Lunch");
MenuComponent dinerMenu = new Menu("Dinner Menu", "Home Style Cooking");
MenuComponent dessertMenu = new Menu("Dessert Menu", "Desserts of the Day");

MenuComponent allMenus = new Menu("All Menus", "Combined Menus");

allMenus.add(breakfastMenu);
allMenus.add(lunchMenu);
allMenus.add(dinerMenu);
dinerMenu.add(new MenuItem("Vegetarian BLT", "(Fakin) Bacon with lettuce & tomato on whole wheat", true, 2.99));

allMenus.print();

输出结果:

All Menus, Combined Menus
---------------------------
Breakfast Menu, All Day Breakfast
---------------------------
Lunch Menu, Delicious Lunch
---------------------------
Dinner Menu, Home Style Cooking
  Vegetarian BLT(v), 2.99
---------------------------

通过以上示例可以看出,Composite组合模式的用法可适用于多种对象组合的场景,提供了一种简便的树形数据结构的设计方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java实现Composite组合模式的实例代码 - Python技术站

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

相关文章

  • java获取整点与凌晨的时间戳

    获取整点与凌晨的时间戳,可以用Java中的Calendar类来实现,这个类可以帮助我们获取日期时间的各个部分,例如年份、月份、日期、小时数、分钟数等,还可以进行日期时间的加减运算。具体实现步骤如下: 1. 获取整点的时间戳 获取当前整点的时间戳,我们可以先获取当前的年、月、日和小时,然后将分钟和秒数置为0,最后再获取时间戳即可。 Calendar calen…

    Java 2023年5月20日
    00
  • SpringBoot自定义注解API数据加密和签名校验

    首先我想说明一下本次攻略的目的和背景。随着网络技术的快速发展,很多 web 应用都包含了用户敏感信息,数据的安全性也变得越来越重要。而其中一个解决方案就是加密和签名校验。SpringBoot 作为一个主流的开发框架,提供了各种扩展点,开发人员可以通过自定义注解来实现各种功能,其中就包括 API 数据加密和签名校验。我们的攻略就是基于 SpringBoot 自…

    Java 2023年5月20日
    00
  • ibatis结合oracle批量插入三种方法的测评

    针对“ibatis结合oracle批量插入三种方法的测评”的完整攻略,我分步骤详细讲解如下: 1. 背景 在使用ibatis结合oracle进行数据插入时,我们常常会遇到需要批量插入大量数据的情况。为了提高插入效率,我们需要考虑如何优化插入方式。本篇攻略将介绍三种常见的批量插入方法,并进行对比测试。 2. 三种批量插入方法的介绍 2.1 JDBC批量插入 使…

    Java 2023年5月20日
    00
  • 深入浅析Centos 7系统的Tomcat服务器

    深入浅析Centos 7系统的Tomcat服务器 简介 Tomcat 是 Apache 软件基金会(Apache Software Foundation)的一款开源的 Java Servlet 容器,也是一个标准的 JSP 容器。 本文将分步讲解如何在 Centos 7 系统上安装和配置 Tomcat 服务器,以及如何在 Tomcat 中部署网站应用。 安装…

    Java 2023年5月19日
    00
  • MyBatis-Plus集成Druid环境搭建的详细教程

    下面我将为你介绍Mybatis-Plus集成Druid环境搭建的详细教程,包括环境搭建、配置和代码演示。首先,我们需要明确一下什么是Mybatis-Plus和Druid。 什么是MyBatis-Plus和Druid? MyBatis-Plus MyBatis-Plus(简称MP)是一个在MyBatis框架基础上的增强工具,省去了很多重复性的代码,提供了更为简…

    Java 2023年5月20日
    00
  • java异常处理throws完成异常抛出详解

    Java异常处理:throws完成异常抛出详解 在Java编程中,异常处理是一个非常重要的知识点。而在进行异常处理时,throws关键字的使用也是一种常见的方式。本文将为您详细讲解使用throws关键字完成异常抛出的过程以及注意事项。 1. 异常处理的三种方式 在Java中,异常处理可以通过三种方式来完成: try-catch块:用于捕捉并处理异常。 thr…

    Java 2023年5月27日
    00
  • Java String创建对象实例解析

    下面我来详细讲解“Java String创建对象实例解析”的完整攻略。 什么是Java String对象 Java中的字符串是一个对象,被封装在Java.lang.String类中。其中包含了很多有用的方法,可供开发者使用。 在Java中创建一个字符串可以有多种方式。创建字符串对象可以通过使用两种不同的方式,即字符串文字或字符串构造函数。 使用字符串文字创建…

    Java 2023年5月26日
    00
  • 什么是动态字节码生成?

    动态字节码生成是指在程序运行过程中通过程序生成字节码并将其加载进JVM,从而实现运行时动态生成代码的一种技术。 使用动态字节码生成的主要场景是:在程序运行过程中,需要根据不同的输入或状态,动态生成代码以完成特定的逻辑。另一个应用场景是AOP框架,其中动态字节码生成技术被用于实现切面编程。 下面是两个示例说明,帮助你更好地理解动态字节码生成的具体使用方法。 示…

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