前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >趣解设计模式之《小店儿菜单的故事》

趣解设计模式之《小店儿菜单的故事》

作者头像
爪哇缪斯
发布2023-09-26 14:05:26
1040
发布2023-09-26 14:05:26
举报
文章被收录于专栏:爪哇缪斯爪哇缪斯

〇、小故事

在一座小镇上,有两家特别有名气的小店,一家是远近闻名的早餐店,它家的早餐特别好吃,每天早上都能排起长长的队伍;另一家是个蛋糕店,他家是专门从法国请来的蛋糕师傅,蛋糕的香味真是香飘万里。

自从听说这个酱香拿铁销量非常高之后,这两家店的老板们就觉得强强联合才是能让小店更进一步的关键,所以,两家老板打算合并起来一起做生意。

但是呢,早餐店的菜单是ArrayList维护的,蛋糕店的菜单是数组维护的。那么对于服务员来说,他报菜单的时候,既要针对ArrayList类型的菜单进行遍历输出菜品,又需要再针对数组进行遍历输出菜品。并且,如果后面合并的小店越来越多,菜单用了其他的数据结构存储怎么办呢?如果强制所有的饭店都使用统一的集合类型去存储菜单的话,那么对小店来说,所有用到旧菜单的地方都需要代码修改。这样改动太大了呀。

为了解决这个问题,我们统一提供了迭代器接口,每个饭店的菜单都要实现迭代器这个接口。那么这就是今天要给大家介绍的设计模式——迭代器模式

一、模式定义

迭代器模式Iterator Pattern

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

二、模式类图

针对上面两个小店合并后菜单类型不一致导致的遍历问题,我们来看一下如何采用迭代模式来解决。首先,我们要创建菜单接口类Menu,以及两个饭店的菜单实现类,分别是:ARestaurantMenuBRestaurantMenu。其次,创建菜单迭代器接口MenuIterator和两个饭店的菜单迭代器实现类,分别是:ARestaurantMenuIteratorBRestaurantMenuIterator。最后,创建服务员类Waitress和菜单项类MenuItem。具体类图请见如下所示:

三、代码实现

创建菜单明细项MenuItem.java

代码语言:javascript
复制
public class MenuItem {
    // 菜名
    private String name;
    // 菜品详细介绍
    private String desc;
    // 是否是素食
    private boolean vegetarian;
    // 菜的价格
    private double price;

    public MenuItem(String name, String desc, boolean vegetarian, double price) {
        this.name = name;
        this.desc = desc;
        this.vegetarian = vegetarian;
        this.price = price;
    }
    /** xxxGet()和xxxSet()方法*/
}

创建小店菜单接口Menu.java

代码语言:javascript
复制
public interface Menu {
    MenuIterator iterator(); // 获得迭代器
}

创建A饭店菜单实现类ARestaurantMenu.java

代码语言:javascript
复制
public class ARestaurantMenu implements Menu {
    private ArrayList<MenuItem> menuItems;
    public ARestaurantMenu() {
        menuItems = new ArrayList<>();
        addItem("油条", "油条的描述", true, 0.5);
        addItem("豆浆", "豆浆的描述", true, 1.9);
        addItem("茶叶蛋", "茶叶蛋的描述", true, 1.5);
        addItem("小笼包", "小笼包的描述", true, 2.1);
    }

    private void addItem(String name, String desc, boolean vegetarian, double price) {
        MenuItem menuItem = new MenuItem(name, desc, vegetarian, price);
        menuItems.add(menuItem);
    }

    public ArrayList<MenuItem> getMenuItems() {
        return menuItems;
    }

    @Override
    public MenuIterator iterator() {
        return new ARestaurantMenuIterator(menuItems);
    }
}

创建B饭店菜单实现类BRestaurantMenu.java

代码语言:javascript
复制
public class BRestaurantMenu implements Menu {
    int nums = 0;
    private static final int MAX_SIZE = 5; // 餐厅老板很有个性,只做5道菜
    private MenuItem[] menuItems;

    public BRestaurantMenu() {
        menuItems = new MenuItem[MAX_SIZE];
        addItem("宫保鸡丁", "宫保鸡丁的描述", true, 0.5);
        addItem("北京烤鸭", "北京烤鸭的描述", true, 1.9);
        addItem("黄焖鸡米饭", "黄焖鸡米饭的描述", true, 1.5);
        addItem("啵啵鱼", "啵啵鱼的描述", true, 2.1);
        addItem("兰州拉面", "兰州拉面的描述", true, 2.1);
    }

    private void addItem(String name, String desc, boolean vegetarian, double price) {
        MenuItem menuItem = new MenuItem(name, desc, vegetarian, price);
        if (nums >= MAX_SIZE) {
            System.out.println("菜单满了!老板不做了!");
            return;
        }
        menuItems[nums++] = menuItem;
    }

    public MenuItem[] getMenuItems() {
        return menuItems;
    }

    @Override
    public MenuIterator iterator() {
        return new BRestaurantMenuIterator(menuItems);
    }
}

创建菜单迭代器接口类MenuIterator.java

代码语言:javascript
复制
public interface MenuIterator {
    // 容器中是否还有元素
    boolean hasNext();
    // 获得容器中的下一个元素
    MenuItem next();
}

创建A饭店的菜单迭代器实现类ARestaurantMenuIterator.java

代码语言:javascript
复制
public class ARestaurantMenuIterator implements MenuIterator {
    private ArrayList<MenuItem> menuItems;
    private Iterator<MenuItem> iterator;

    public ARestaurantMenuIterator(ArrayList<MenuItem> menuItems) {
        this.menuItems = menuItems;
        iterator = menuItems.iterator();
    }

    @Override
    public boolean hasNext() {
        return iterator.hasNext();
    }

    @Override
    public MenuItem next() {
        return iterator.next();
    }
}

创建B饭店的菜单迭代器实现类BRestaurantMenuIterator.java

代码语言:javascript
复制
public class BRestaurantMenuIterator implements MenuIterator {
    private MenuItem[] menuItems;
    private int i = 0;

    public BRestaurantMenuIterator(MenuItem[] menuItems) {
        this.menuItems = menuItems;
    }

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

    @Override
    public MenuItem next() {
        return menuItems[i++];
    }
}

创建服务员类Waitress.java

代码语言:javascript
复制
public class Waitress {
    /** 服务员打印菜单 */
    public void printMenu(Menu... menus) {
        for (Menu menu : menus) {
            print(menu.iterator());
        }
    }

    private void print(MenuIterator iterator) {
        MenuItem menuItem;
        while (iterator.hasNext()) {
            menuItem = iterator.next();
            System.out.println(String.format("name=%s, desc=%s, price=%s", menuItem.getName(), 
                                             menuItem.getDesc(), menuItem.getPrice()));
        }
    }
}

创建测试类IteratorTest.java

代码语言:javascript
复制
public class IteratorTest {
    public static void main(String[] args) {
        /** 构建A餐馆和B餐馆的菜单 */
        ARestaurantMenu aMenu = new ARestaurantMenu();
        BRestaurantMenu bMenu = new BRestaurantMenu();
        /** 构建女服务员 */
        Waitress waitress = new Waitress();
        /** 将A餐馆和B餐馆的菜单传给服务员,让她报出菜单来 */
        waitress.printMenu(aMenu, bMenu);
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-09-26 09:30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爪哇缪斯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 〇、小故事
  • 一、模式定义
  • 二、模式类图
  • 三、代码实现
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档