【HeadFirst系列之HeadFirst设计模式】第10天之迭代器与组合模式:遍历与管理的艺术

news/2025/2/24 17:17:04

迭代器与组合模式:遍历与管理的艺术

在《Head First 设计模式》中,**迭代器模式(Iterator Pattern)组合模式(Composite Pattern)**是两个非常重要的设计模式迭代器模式帮助我们遍历集合中的元素,而组合模式则帮助我们管理树形结构的对象。这两种模式在实际开发中有着广泛的应用,尤其是在JDK和Spring等框架中。今天,我们将通过书中的内容,结合代码示例,来深入理解这两种模式。

在这里插入图片描述


迭代器模式:遍历集合的艺术

迭代器模式的定义是:

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

简单来说,迭代器模式将遍历集合的责任从集合类中分离出来,交给一个独立的迭代器对象。这样,集合类可以专注于管理元素,而迭代器类可以专注于遍历元素。

迭代器模式的核心思想

  1. 分离遍历与集合:将遍历集合的逻辑从集合类中分离出来,交给迭代器类。
  2. 统一的遍历接口:通过统一的接口(如 Iterator),可以遍历不同类型的集合。

代码示例:迭代器模式

我们通过一个简单的例子来理解迭代器模式。假设我们有一个菜单系统,包含两个菜单:PancakeHouseMenuDinerMenu。我们希望遍历这两个菜单中的所有菜品。

定义菜单项

class MenuItem {
    String name;
    double price;

    MenuItem(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}

定义菜单

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

class PancakeHouseMenu {
    private List<MenuItem> menuItems;

    PancakeHouseMenu() {
        menuItems = new ArrayList<>();
        addItem("K&B's Pancake Breakfast", 2.99);
        addItem("Regular Pancake Breakfast", 2.99);
        addItem("Blueberry Pancakes", 3.49);
    }

    void addItem(String name, double price) {
        menuItems.add(new MenuItem(name, price));
    }

    Iterator<MenuItem> createIterator() {
        return menuItems.iterator();
    }
}

class DinerMenu {
    private static final int MAX_ITEMS = 6;
    private int numberOfItems = 0;
    private MenuItem[] menuItems;

    DinerMenu() {
        menuItems = new MenuItem[MAX_ITEMS];
        addItem("Vegetarian BLT", 2.99);
        addItem("BLT", 2.99);
        addItem("Soup of the day", 3.29);
    }

    void addItem(String name, double price) {
        if (numberOfItems >= MAX_ITEMS) {
            System.out.println("Sorry, menu is full!");
        } else {
            menuItems[numberOfItems] = new MenuItem(name, price);
            numberOfItems++;
        }
    }

    Iterator<MenuItem> createIterator() {
        return new DinerMenuIterator(menuItems);
    }
}

定义迭代器

import java.util.Iterator;

class DinerMenuIterator implements Iterator<MenuItem> {
    private MenuItem[] items;
    private int position = 0;

    DinerMenuIterator(MenuItem[] items) {
        this.items = items;
    }

    @Override
    public boolean hasNext() {
        return position < items.length && items[position] != null;
    }

    @Override
    public MenuItem next() {
        MenuItem menuItem = items[position];
        position++;
        return menuItem;
    }
}

测试代码

public class MenuTest {
    public static void main(String[] args) {
        PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
        DinerMenu dinerMenu = new DinerMenu();

        Iterator<MenuItem> pancakeIterator = pancakeHouseMenu.createIterator();
        Iterator<MenuItem> dinerIterator = dinerMenu.createIterator();

        System.out.println("MENU\n----\nBREAKFAST");
        printMenu(pancakeIterator);

        System.out.println("\nLUNCH");
        printMenu(dinerIterator);
    }

    private static void printMenu(Iterator<MenuItem> iterator) {
        while (iterator.hasNext()) {
            MenuItem menuItem = iterator.next();
            System.out.println(menuItem.getName() + ", " + menuItem.getPrice());
        }
    }
}

输出结果:

MENU
----
BREAKFAST
K&B's Pancake Breakfast, 2.99
Regular Pancake Breakfast, 2.99
Blueberry Pancakes, 3.49

LUNCH
Vegetarian BLT, 2.99
BLT, 2.99
Soup of the day, 3.29

组合模式:管理树形结构的艺术

组合模式的定义是:

将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

简单来说,组合模式允许我们将对象组合成树形结构,并且可以像处理单个对象一样处理整个树形结构。

组合模式的核心思想

  1. 统一叶子节点和组合节点:叶子节点和组合节点实现相同的接口,用户可以一致地处理它们。
  2. 递归结构:组合节点可以包含其他组合节点或叶子节点,形成递归结构。

代码示例:组合模式

我们通过一个简单的例子来理解组合模式。假设我们有一个菜单系统,菜单可以包含子菜单和菜单项。

定义组件接口

interface MenuComponent {
    void print();
}

定义叶子节点(菜单项)

class MenuItem implements MenuComponent {
    private String name;
    private double price;

    MenuItem(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public void print() {
        System.out.println(name + ", " + price);
    }
}

定义组合节点(菜单)

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

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

    Menu(String name) {
        this.name = name;
    }

    void add(MenuComponent menuComponent) {
        menuComponents.add(menuComponent);
    }

    @Override
    public void print() {
        System.out.println("\n" + name);
        System.out.println("---------------------");
        for (MenuComponent menuComponent : menuComponents) {
            menuComponent.print();
        }
    }
}

测试代码

public class MenuTest {
    public static void main(String[] args) {
        MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU");
        pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast", 2.99));
        pancakeHouseMenu.add(new MenuItem("Regular Pancake Breakfast", 2.99));

        MenuComponent dinerMenu = new Menu("DINER MENU");
        dinerMenu.add(new MenuItem("Vegetarian BLT", 2.99));
        dinerMenu.add(new MenuItem("BLT", 2.99));

        MenuComponent allMenus = new Menu("ALL MENUS");
        allMenus.add(pancakeHouseMenu);
        allMenus.add(dinerMenu);

        allMenus.print();
    }
}

输出结果:

ALL MENUS
---------------------

PANCAKE HOUSE MENU
---------------------
K&B's Pancake Breakfast, 2.99
Regular Pancake Breakfast, 2.99

DINER MENU
---------------------
Vegetarian BLT, 2.99
BLT, 2.99

迭代器与组合模式在JDK和Spring中的应用

1. JDK中的迭代器模式

JDK中的 java.util.Iterator 接口是迭代器模式的典型实现。例如,ArrayListHashSet 都提供了 iterator() 方法,用于返回一个迭代器对象。

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

2. Spring中的组合模式

Spring框架中的 org.springframework.core.io.Resource 接口是组合模式的典型实现。Resource 接口既可以表示单个资源(如文件),也可以表示多个资源(如目录)。

Resource resource = new FileSystemResource("file.txt");
System.out.println(resource.getFilename());

总结

迭代器模式组合模式是两个非常重要的设计模式迭代器模式帮助我们遍历集合中的元素,而组合模式则帮助我们管理树形结构的对象。这两种模式在实际开发中有着广泛的应用,尤其是在JDK和Spring等框架中。

通过《Head First 设计模式》中的内容,我们深入理解了这两种模式的核心思想,并通过代码示例掌握了它们的实际应用。希望这篇文章能帮助你更好地理解迭代器模式组合模式,并在实际开发中灵活运用它们!


互动话题:你在实际开发中使用过迭代器模式组合模式吗?欢迎在评论区分享你的经验和心得!


http://www.niftyadmin.cn/n/5864636.html

相关文章

pikachu靶场搭建教程

需要的东西 phpStudy&#xff1a; 链接&#xff1a; https://pan.baidu.com/s/1fJ-5TNtdDZGUf5FhTm245g 提取码&#xff1a;0278 pikachu-master&#xff1a; Github链接&#xff1a;https://github.com/zhuifengshaonianhanlu/pikachu 链接&#xff1a; https://pan.baidu.c…

Java实现斗地主-做牌以及对牌排序

卡牌类 public class Card {private String size;//大小private String color;//花色private int value;//权值public Card() {}public Card(String size, String color, int value) {this.size size;this.color color;this.value value;}public String toString(){return …

vue2 和 vue3 中 computer 计算属性的用法

Vue 2 中的 computed 在 Vue 2 中&#xff0c;计算属性是响应式的&#xff0c;并且基于 getter 进行缓存&#xff0c;只有依赖的响应式数据发生变化时才会重新计算。 基本用法 <template><div><p>原始消息&#xff1a;{{ message }}</p><p>反…

22.回溯算法4

递增子序列 这里不能排序&#xff0c;因为数组的顺序是对结果有影响的&#xff0c;所以只能通过used数组来去重 class Solution { public:vector<int> path;vector<vector<int>> res;void backtracking(vector<int>& nums,int start){if(path.si…

“国补”带火手机换新,出售旧手机应如何保护个人信息安全

在“国补”政策的推动下,手机换新热潮正席卷而来。“国补”以其诱人的补贴力度,成功激发了消费者更换手机的热情。无论是渴望体验最新技术的科技爱好者,还是对旧手机性能不满的普通用户,都纷纷投身到这场手机换新的浪潮之中。 随着大量消费者参与手机换新,二手手机市场迎来…

机器学习数学通关指南——拉格朗日乘子法

前言 本文隶属于专栏《机器学习数学通关指南》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见《机器学习数学通关指南》 正文 一句话总结 拉格朗日乘子法…

Python采用DeepSeekR1本地部署+本地API接口实现简单对话

以下内容摘抄自 【Ai】— DeepSeek-r1 版本选择(超详细)https://blog.csdn.net/weixin_44205779/article/details/145479506 Ollama:零代码部署大模型,轻松玩转AIhttps://blog.csdn.net/scy799327210/article/details/145798396 大模型 ollama命令详解大全https://blog.…

DeepSeek学习教程 从入门到精通pdf下载:快速上手 DeepSeek

下载链接&#xff1a;DeepSeek从入门到精通(清华大学).pdf 链接: https://pan.baidu.com/s/1Ym0-_x9CrFHFld9UiOdA5A 提取码: 2ebc 一、DeepSeek 简介 DeepSeek 是一款由中国团队开发的高性能大语言模型&#xff0c;具备强大的推理能力和对中文的深刻理解。它广泛应用于智能办…