• 《Head First 设计模式》:迭代器模式


    正文

    一、定义

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

    要点:

    • 迭代器模式把在元素之间游走的责任交给迭代器,而不是聚合对象。这样简化了聚合的接口和实现,也让责任各得其所。

    二、实现步骤

    1、创建迭代器接口

    /**
     * 迭代器接口
     */
    public interface Iterator {
    
        /**
         * 是否有下一个元素
         */
        public boolean hasNext();
        
        /**
         * 获取下一个元素
         */
        public Object next();
    }
    

    2、创建具体迭代器,并实现迭代器接口

    具体迭代器负责遍历元素,以及管理目前遍历的位置。

    /**
     * 具体迭代器
     */
    public class ConcreteIterator implements Iterator {
        
        /**
         * 要遍历的集合(数组)
         */
        public String[] items;
        /**
         * 当前遍历位置
         */
        int position = 0;
        
        public ConcreteIterator(String[] items) {
            this.items = items;
        }
    
        @Override
        public boolean hasNext() {
            if (position < items.length) {
                return true;
            }
            return false;
        }
    
        @Override
        public Object next() {
            if (!this.hasNext()) {
                return null;
            }
            String item = items[position];
            position = position + 1;
            return item;
        }
    }
    

    3、创建聚合接口,并定义返回迭代器的方法

    /**
     * 聚合接口
     */
    public interface Aggregate {
    
        /**
         * 创建迭代器
         */
        public Iterator createIterator();
    }
    

    4、创建具体聚合,并实现返回迭代器的方法

    具体聚合里面持有集合。这里的集合指的是一群对象,其存储方式可以是列表、数组、散列表等。

    /**
     * 具体聚合
     */
    public class ConcreteAggregate implements Aggregate {
        
        /**
         * 持有集合(比如列表、数组、散列表等)
         */
        public String[] items = new String[] {"item1", "item2", "item3"};
    
        @Override
        public Iterator createIterator() {
            return new ConcreteIterator(items);
        }
    }
    

    5、使用迭代器进行遍历

    public class Test {
        
        public static void main(String[] args) {
            // 聚合对象
            Aggregate aggregate = new ConcreteAggregate();
            // 迭代器
            Iterator iterator = aggregate.createIterator();
            // 遍历
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
    }
    

    三、举个栗子

    1、背景

    对象村餐厅和对象村煎饼屋合并了,现在我们可以在同一个地方,享用煎饼屋美味的煎饼早餐和好吃的餐厅午餐了。

    假设你被他们合组的新公司雇佣,打算创建一个 Java 版本的女招待。这个 Java 版本的女招待规格是:能应对顾客的需要打印定制的菜单,而无需询问厨师。

    现在,有一点小麻烦:煎饼屋菜单使用 ArrayList 记录菜单项,而餐厅则是使用数组记录菜单项。两者都不愿意改变他们的实现,毕竟有太多代码依赖于它们了。

    好消息是,煎饼屋和餐厅都同意实现一个统一的菜单项 MenuItem。

    2、实现

    将集合的遍历交给迭代器,这样就不用关心菜单是使用 ArrayList 还是数组记录菜单项了。

    (1)创建菜单项

    /**
     * 菜单项
     */
    public class MenuItem {
    
        String name;
        double price;
        
        public MenuItem(String name, double price) {
            this.name = name;
            this.price = price;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    }
    

    (2)创建迭代器接口

    /**
     * 迭代器接口
     */
    public interface Iterator {
    
        /**
         * 是否有下一个元素
         */
        public boolean hasNext();
        
        /**
         * 获取下一个元素
         */
        public Object next();
    }
    

    (3)创建具体的菜单迭代器

    /**
     * 煎饼屋菜单迭代器
     */
    public class PancakeHouseMenuIterator implements Iterator {
        
        /**
         * 列表形式的菜单项
         */
        public ArrayList<MenuItem> menuItems;
        int position = 0;
        
        public PancakeHouseMenuIterator(ArrayList<MenuItem> items) {
            this.menuItems = items;
        }
    
        @Override
        public boolean hasNext() {
            if (position < menuItems.size()) {
                return true;
            }
            return false;
        }
    
        @Override
        public Object next() {
            if (!this.hasNext()) {
                return null;
            }
            MenuItem item = menuItems.get(position);
            position = position + 1;
            return item;
        }
    }
    
    /**
     * 餐厅菜单迭代器
     */
    public class DinerMenuIterator implements Iterator {
        
        /**
         * 数组形式的菜单项
         */
        public MenuItem[] menuItems;
        int position = 0;
        
        public DinerMenuIterator(MenuItem[] items) {
            this.menuItems = items;
        }
    
        @Override
        public boolean hasNext() {
            if (position < menuItems.length) {
                return true;
            }
            return false;
        }
    
        @Override
        public Object next() {
            if (!this.hasNext()) {
                return null;
            }
            MenuItem item = menuItems[position];
            position = position + 1;
            return item;
        }
    }
    

    (4)创建菜单接口

    /**
     * 菜单接口
     */
    public interface Menu {
    
        /**
         * 创建迭代器
         */
        public Iterator createIterator();
    }
    

    (5)创建具体的菜单

    /**
     * 煎饼屋菜单
     */
    public class PancakeHouseMenu implements Menu {
        
        public ArrayList<MenuItem> menuItems;
        
        public PancakeHouseMenu() {
            menuItems = new ArrayList<MenuItem>();
            menuItems.add(new MenuItem("Regular Pancake Breakfast", 2.99));
            menuItems.add(new MenuItem("Blueberry Pancakes", 3.49));
            menuItems.add(new MenuItem("Waffles", 3.59));
        }
    
        @Override
        public Iterator createIterator() {
            return new PancakeHouseMenuIterator(menuItems);
        }
    }
    
    /**
     * 餐厅菜单
     */
    public class DinerMenu implements Menu {
        
        public MenuItem[] menuItems;
        
        public DinerMenu() {
            menuItems = new MenuItem[3];
            menuItems[0] = new MenuItem("BLT", 2.99);
            menuItems[1] = new MenuItem("Soup of the day", 3.29);
            menuItems[2] = new MenuItem("Hotdog", 3.05);
        }
    
        @Override
        public Iterator createIterator() {
            return new DinerMenuIterator(menuItems);
        }
    }
    

    (6)创建女招待

    /**
     * 女招待
     */
    public class Waitress {
        
        Menu pancakeHouseMenu;
        Menu dinerMenu;
        
        public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
            this.pancakeHouseMenu = pancakeHouseMenu;
            this.dinerMenu = dinerMenu;
        }
        
        public void printMenu() {
            // 获取菜单迭代器
            Iterator pancakeIterator = pancakeHouseMenu.createIterator();
            Iterator dinerIterator = dinerMenu.createIterator();
            // 使用迭代器打印菜单
            System.out.println("----MENU----
    ");
            System.out.println("BREAKFASE:");
            printMenu(pancakeIterator);
            System.out.println("
    LUNCH:");
            printMenu(dinerIterator);
        }
        
        private void printMenu(Iterator iterator) {
            while (iterator.hasNext()) {
                MenuItem menuItem = (MenuItem)iterator.next();
                System.out.println(menuItem.getName() + ", " + menuItem.getPrice());
            }
        }
    }
    

    (7)使用女招待打印菜单

    public class Test {
        
        public static void main(String[] args) {
            // 菜单
            Menu pancakeHouseMenu = new PancakeHouseMenu();
            Menu dinerMenu = new DinerMenu();
            // 女招待
            Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
            // 打印菜单
            waitress.printMenu();
        }
    }
    
  • 相关阅读:
    职工工资管理系统 c++课程设计
    我的Python自学之路四,字符串的学习
    我的Python自学之路三:元组及字典学习总结
    我的Python自学之路二:列表学习
    我的Python自学之路一:Python学习路线
    vue项目里在微信浏览器调用微信分享及支付一些页面数据的坑
    vue 三种传值方法
    vue里swiper的一些坑
    js 数据导出为txt文件
    js 小数计算为啥和想象中不一样!
  • 原文地址:https://www.cnblogs.com/jingqueyimu/p/13629551.html
Copyright © 2020-2023  润新知