Java设计模式 二十五 组合模式 + 迭代器模式

组合模式 + 迭代器模式

组合模式迭代器模式经常组合使用,主要用于处理树形结构的数据并对其进行遍历操作。组合模式负责构建层次化的对象结构,而迭代器模式则提供了统一的方式来遍历这些对象结构。


1. 使用场景

组合模式和迭代器模式的组合非常适合以下场景:

  1. 文件系统: 文件夹和文件的组合,迭代器可以用于遍历整个文件系统。
  2. 菜单系统: 多级菜单的管理,迭代器可以用于逐项遍历菜单项。
  3. 组织架构: 部门和子部门的层次结构,迭代器用于遍历所有部门和员工。

2. 实现示例:菜单系统

我们来实现一个餐厅的菜单系统,其中菜单项(叶子节点)和菜单(组合节点)构成树形结构。组合模式用于管理菜单和菜单项的层次关系,迭代器模式用于遍历所有的菜单项。


(1) 定义组件接口

MenuComponent作为统一接口,定义了菜单项和菜单的公共操作。

// 组件接口
public abstract class MenuComponent {
    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

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

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

    public String getName() {
        throw new UnsupportedOperationException();
    }

    public String getDescription() {
        throw new UnsupportedOperationException();
    }

    public boolean isVegetarian() {
        throw new UnsupportedOperationException();
    }

    public double getPrice() {
        throw new UnsupportedOperationException();
    }

    public void print() {
        throw new UnsupportedOperationException();
    }

    public Iterator<MenuComponent> createIterator() {
        throw new UnsupportedOperationException();
    }
}

(2) 定义叶子节点

MenuItem类是叶子节点,表示菜单中的单个项。

// 菜单项(叶子节点)
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 boolean isVegetarian() {
        return vegetarian;
    }

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

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

(3) 定义组合节点

Menu类是组合节点,表示菜单,可以包含子菜单或菜单项。

// 菜单(组合节点)
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

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 i) {
        return menuComponents.get(i);
    }

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

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

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

        Iterator<MenuComponent> iterator = menuComponents.iterator();
        while (iterator.hasNext()) {
            MenuComponent menuComponent = iterator.next();
            menuComponent.print();
        }
    }

    @Override
    public Iterator<MenuComponent> createIterator() {
        return menuComponents.iterator();
    }
}

(4) 客户端代码

客户端代码创建了一个包含多个菜单和菜单项的层次结构,并使用组合模式和迭代器模式进行遍历和打印。

public class Client {
    public static void main(String[] args) {
        // 创建菜单项
        MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", "Breakfast");
        MenuComponent dinerMenu = new Menu("DINER MENU", "Lunch");
        MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner");

        MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");

        // 将子菜单加入到顶级菜单中
        allMenus.add(pancakeHouseMenu);
        allMenus.add(dinerMenu);
        allMenus.add(cafeMenu);

        // 添加菜单项到子菜单
        pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99));
        pancakeHouseMenu.add(new MenuItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99));

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

        cafeMenu.add(new MenuItem("Veggie Burger and Air Fries", "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", true, 3.99));
        cafeMenu.add(new MenuItem("Soup of the day", "A cup of the soup of the day, with a side salad", false, 3.69));

        // 打印整个菜单结构
        allMenus.print();
    }
}

运行结果:
ALL MENUS
, All menus combined
---------------------

PANCAKE HOUSE MENU
, Breakfast
---------------------
  K&B's Pancake Breakfast(v), 2.99
    -- Pancakes with scrambled eggs, and toast
  Regular Pancake Breakfast, 2.99
    -- Pancakes with fried eggs, sausage

DINER MENU
, Lunch
---------------------
  Vegetarian BLT(v), 2.99
    -- (Fakin’) Bacon with lettuce & tomato on whole wheat
  BLT, 2.99
    -- Bacon with lettuce & tomato on whole wheat

CAFE MENU
, Dinner
---------------------
  Veggie Burger and Air Fries(v), 3.99
    -- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
  Soup of the day, 3.69
    -- A cup of the soup of the day, with a side salad

3. 优点

  1. 组合模式的层次管理: 菜单和菜单项可以组合成树形结构,方便管理和维护。
  2. 迭代器模式的统一遍历: 使用迭代器模式可以对组合节点和叶子节点进行统一遍历,无需关心具体类型。
  3. 灵活性高: 组合模式使得菜单结构可以自由扩展,迭代器模式简化了遍历逻辑。

4. 总结

组合模式适合处理树形结构中的“部分-整体”关系,而迭代器模式为复杂的树形结构提供了统一的遍历方式。两者的组合是许多应用场景(如文件系统、菜单系统、组织架构)中的经典设计模式,有助于构建灵活、可扩展的系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十方来财

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值