java设计模式-组合模式详解

Java设计模式-组合模式详解

什么是组合模式?

组合模式属于结构型设计模式,它将对象组合成树形结构,以表示'部分-整体'的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性,通常适用于处理树形结构,或者希望将单个对象和组合对象以相同的方式进行处理。

组合模式主要包含以下两种角色:

  • Component(抽象构件):定义了叶子和容器构件的公用接口,并提供默认实现

  • Leaf(叶子构件):在组合结构中表示叶子节点对象,它实现了Component接口的操作,但是叶子节点没有子节点

  • Composite(容器构件):表示容器节点对象,它实现了Component接口的操作,并且包含或管理子节点(即Leaf和Composite)

组合模式的优点是什么?

在使用组合模式时,可以获得以下优点:

  • 简化客户端操作,将单个对象和组合对象看作一致,无需过多考虑对象的层次结构

  • 客户可以一致性的使用组合结构中所有对象

  • 方便增加新的构件,符合开闭原则

组合模式示例1: 文件系统

现在我们使用组合模式实现一个文件系统,文件系统包含文件夹和文件两种对象,文件夹可以包含文件夹或文件。文件系统操作包含创建文件夹、创建文件、删除文件夹、删除文件以及展示文件和文件夹等。

public interface FileSystem {
    void show(String prefix);
    String getName();
}

public class Folder implements FileSystem {
    private final String name;
    private final List<FileSystem> files;

    public Folder(String name) {
        this.name = name;
        this.files = new ArrayList<>();
    }

    @Override
    public void show(String prefix) {
        System.out.println(prefix + name);
        prefix += "    "; // 缩进处理
        for (FileSystem file : files) {
            file.show(prefix);
        }
    }

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

    public void addFile(FileSystem file) {
        files.add(file);
    }

    public void removeFile(FileSystem file) {
        files.remove(file);
    }
}

public class File implements FileSystem {
    private final String name;

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

    @Override
    public void show(String prefix) {
        System.out.println(prefix + name);
    }

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

示例2: 饮品现场下单系统

在饮品下单系统中,有饮品和套餐两种对象,套餐对象包含了饮品和其他套餐,它们都可以打印出订单中的内容。具体的代码实现如下:

public abstract class Drink {
    protected final String name;
    protected final Double price;

    public Drink(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    public void print() {
        System.out.println(name + " : ¥" + price);
    }

    public Double getPrice() {
        return price;
    }
}

public class Coffee extends Drink {
    public Coffee(String name, Double price) {
        super(name, price);
    }
}

public class Juice extends Drink {
    public Juice(String name, Double price) {
        super(name, price);
    }
}

public class Meal {
    protected final String name;
    protected final Double price;
    protected final List<Drink> drinks;

    public Meal(String name) {
        this.name = name;
        this.price = 0.0;
        this.drinks = new ArrayList<>();
    }

    public Meal(String name, Double price) {
        this.name = name;
        this.price = price;
        this.drinks = new ArrayList<>();
    }

    public void addDrink(Drink drink) {
        drinks.add(drink);
    }

    public void removeDrink(Drink drink) {
        drinks.remove(drink);
    }

    public Double getPrice() {
        Double totalPrice = price;
        for (Drink drink : drinks) {
            totalPrice += drink.getPrice();
        }
        return totalPrice;
    }

    public void print() {
        System.out.println(String.format("套餐名称:%s, 价格:¥%.2f", name, getPrice()));
        System.out.println("饮品列表:");
        for (Drink drink : drinks) {
            drink.print();
        }
    }
}

public class SetMeal extends Meal {
    private final List<Meal> meals;

    public SetMeal(String name, Double price) {
        super(name, price);
        this.meals = new ArrayList<>();
    }

    public void addMeal(Meal meal) {
        meals.add(meal);
    }

    public void removeMeal(Meal meal) {
        meals.remove(meal);
    }

    @Override
    public Double getPrice() {
        Double totalPrice = price;
        for (Meal meal : meals) {
            totalPrice += meal.getPrice();
        }
        for (Drink drink : drinks) {
            totalPrice += drink.getPrice();
        }
        return totalPrice;
    }

    @Override
    public void print() {
        System.out.println(String.format("套餐名称:%s, 价格:¥%.2f", name, getPrice()));
        System.out.println("套餐包含:");
        for (Meal meal : meals) {
            meal.print();
        }
        System.out.println("饮品列表:");
        for (Drink drink : drinks) {
            drink.print();
        }
    }
}

以上就是组合模式的详解,包括了什么是组合模式、优点以及两个示例。使用组合模式可以非常方便地处理树形结构的数据,提高代码的可读性和可维护性,是一种非常实用的设计模式。

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

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

相关文章

  • 详解如何在Spring Security中自定义权限表达式

    在对Spring Security中自定义权限表达式的攻略之前,先简单介绍一下权限表达式的作用: Spring Security中的权限表达式用于在方法调用或请求访问时,判断当前用户是否具有访问权限。Spring Security提供了很多默认的权限表达式,例如”hasRole()”和”hasAnyRole()”等。但是,我们有时需要根据不同的业务需求来自定…

    Java 2023年5月20日
    00
  • java导出生成csv文件的方法

    下面我来讲解一下Java导出生成CSV文件的方法。 步骤一:引入CSV依赖 CSV是指Comma Separated Values,即逗号分隔值。在Java中,我们需要引入一个CSV操作的依赖包,这里我们以OpenCSV为例。可以通过以下方式引入依赖: <dependency> <groupId>com.opencsv</gro…

    Java 2023年5月26日
    00
  • spring security CSRF防护的示例代码

    下面我将为你详细讲解如何实现spring security CSRF防护的示例代码。 一、使用spring security实现CSRF防护的原理 Spring Security主要通过以下两种方式实现CSRF防护: CSRF Token 在用户登录后,在服务器端生成一个Token,将该Token发送给前端页面。在前端页面的每一个提交操作中,都需要将这个To…

    Java 2023年5月20日
    00
  • Mybatis一对多与多对一查询处理详解

    Mybatis一对多与多对一查询处理详解 Mybatis是一个支持高度定制化SQL查询、缓存处理和参数映射的框架。在Mybatis中,一对多与多对一的查询是非常常见和重要的使用情景。本文将详细介绍Mybatis一对多与多对一查询的处理方法。 一对多查询 一对多查询指的是,在表之间通过一个外键关联形成的一种关系,即一个父对象对应多个子对象。下面是一个一对多的示…

    Java 2023年5月20日
    00
  • List集合多线程并发条件下不安全如何解决

    List集合在多线程并发条件下存在线程安全问题,主要是由于多个线程在同时对List进行增删改操作,会产生竞争条件。在此情况下,如果不进行处理,会导致List集合数据不一致或者抛出ConcurrentModificationException异常等问题。下面是解决List集合多线程并发不安全的完整攻略: 方案1:使用线程安全的List集合 Java提供了多个线…

    Java 2023年5月26日
    00
  • kafka topic 权限控制(设置删除权限)

    针对 Kafka topic 权限控制问题,可以采用以下步骤: 1. 启用Kafka权限控制特性 首先需要在Kafka的配置文件 server.properties 中启用权限控制特性。可以找到如下配置项: authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer 该配置项使用 SimpleA…

    Java 2023年5月20日
    00
  • 剑指Offer之Java算法习题精讲链表专项训练

    剑指Offer之Java算法习题精讲链表专项训练 简介 这是一套针对Java语言的链表算法习题集合,帮助Java程序员加强对链表数据结构的理解和应用。 攻略 学习前的准备 在开始刷题之前,需要掌握Java语言的基本语法和常用数据结构的使用,特别是链表的定义和操作方法。可以先学习一些基础的链表算法,例如反转链表、合并有序链表等。 刷题步骤 第一步:熟练掌握链表…

    Java 2023年5月19日
    00
  • 排序算法的Java实现全攻略

    下面是详细的“排序算法的Java实现全攻略”: 前言 排序是程序员工作日常中经常需要进行的操作之一。在排序过程中,我们需要对数据进行重新排列,从而让它们按照一定的顺序排列。排序算法是实现这一目标的关键,因此排序算法是学习数据结构和算法的重要部分。本文主要介绍Java中常用的排序算法,并给出相应的代码实现。希望读者通过此文能够深入理解排序算法的运行原理,并能够…

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