zoukankan      html  css  js  c++  java
  • 设计模式:迭代器模式

      迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上,这样就简化了聚合的接口,也让责任各得其所。

      场景:有一家早餐店和一家晚餐店合并成一家餐厅,现对两个餐厅的菜单进行合并,两家菜单都一样,有name,decription,price,vegetarian属性,而早餐店的菜单是存放在List集合中,晚餐店的菜单存放在数组中,并且对晚餐的菜单数量进行了限制,不想品种太多。这时候如果服务员需要打印菜单,就可以写for循环遍历List,并转换成菜单类输出,同样,用for循环遍历数组,那如果有十几家餐厅合并呢,那不是要写十个for循环了吗?这时候,我们就来看看迭代器模式怎么解决这问题的。

      首先,我们创建一个菜单项类,表示具体的食物

    //菜单项类
    public class MenuItem {
        String name;
        String description;
        boolean vegetarian;
        double price;
        
        public MenuItem(String name,String description,boolean  vegetarian,double price){
            this.name = name;
            this.description = description;
            this.vegetarian = vegetarian;
            this.price = price;
        }
      //  get方法  
    }

      接着我们创建一个迭代器接口,并且让实现早餐迭代器和晚餐迭代器

    //迭代器接口
    public interface Iterator {
        //判断是否还有元素
        boolean hasNext();
        //返回下一个元素
        Object next();
    }
    
    //早餐类迭代器
    public class PancakeHouseMenuIterator implements Iterator{
        ArrayList items;
        int position = 0;
        
        public  PancakeHouseMenuIterator(ArrayList items){
            this.items = items;
        }
        
        @Override
        public Object next(){
            MenuItem menuItem = (MenuItem)items.get(position);
            position ++;
            return menuItem;
        }
    
        @Override
        public boolean hasNext() {
           if(position >= items.size() || items.get(position) == null){
               return false;
           }
           else{
               return true;
           }
        }
    }
    
    //晚餐菜单的迭代器
    public class DinerMenuIterator implements Iterator{
        MenuItem[] items;
        //记录当前数组变量的位置
        int position = 0;
        
        public  DinerMenuIterator(MenuItem[] items){
            this.items = items;
        }
        
        @Override
        public Object next(){
            MenuItem menuItem = items[position];
            position ++;
            return menuItem;
        }
    
        @Override
        public boolean hasNext() {
           if(position >= items.length || items[position] == null){
               return false;
           }
           else{
               return true;
           }
        }
    }

      然后我们创建菜单接口,让早餐店和晚餐点的菜单实现这个接口

    //由于早餐店菜单的方法和晚餐店菜单的方法很类似,所以我们可以定义一个接口来减少Waitress与具体类的依赖,比较我们要针对接口编程,而不针对实现编程
    //菜单接口
    public interface Menu {
        public void addItem(String name,String description,boolean vegetarian,double price);
        public Iterator createIterator();
    }
    
    public class DinerMenu implements Menu{
        //限制晚餐菜单品种个数
        static final int MAX_ITEMS = 6;
        //记录菜单项的长度
        int numberOfItems = 0;
        MenuItem[] menuItems;
        
        public DinerMenu(){
            menuItems = new MenuItem[MAX_ITEMS];
            
            addItem("火焰牛排","用火焰点缀的牛排",false,98.0);
            addItem("红烧牛肉面","香辣可口的牛肉面",false,23.5);
            addItem("土豆丝盖浇饭","酸酸辣辣的土豆丝",true,10.0);
            addItem("蔬菜沙拉","新鲜蔬菜拌上沙拉酱",true,9.0);
            
        }
        
        @Override
        public void addItem(String name,String description,boolean vegetarian,double price){
            MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
            if(numberOfItems >= MAX_ITEMS){
                System.err.println("菜单满了,不能添加了!");
            }
            else{
                menuItems[numberOfItems] = menuItem;
                numberOfItems = numberOfItems + 1;
            }
        }
    
        //加入一个方法创建一个DinerMenuIterator并返回给客户
        @Override
        public Iterator createIterator(){
            return new DinerMenuIterator(menuItems);
        }
    }
    
    //早餐类
    public class PancakeHouseMenu implements Menu {
        
        ArrayList menuItems;
        
        public PancakeHouseMenu(){
            //初始化早餐菜单
            menuItems = new ArrayList();
            
            addItem("里脊鸡蛋饼","鸡蛋和面粉融合并煎烤而成",false,8.0);
            addItem("青菜包","新鲜青菜与面粉融合",true,1.5);
            addItem("豆腐包","丝滑豆腐与面粉融合",true,1.5);
            addItem("豆浆","现磨黄豆",true,2.5);
        }
        
        @Override
        public void addItem(String name,String description,boolean vegetarian,double price){
            MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
            menuItems.add(menuItem);
        }
        
        //加入一个方法创建一个PancakeHouseMenuIterator并返回给客户
        @Override
           public Iterator createIterator(){
               return new PancakeHouseMenuIterator(menuItems);
           }
    }

      最后我们还要创建一个服务员类

    //服务员类,用来合并菜单
    public class Waitress {
        Menu pancakeHouseMenu;
        Menu dinerMenu;
        
        //我们其实可以把菜单存在一个List传过来,这里为了方便就直接写两个菜单参数了
        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("早餐的菜单:");
            printMenu(pancakeIterator);
            System.out.println();
            System.out.println("晚餐菜单:");
            printMenu(dinerIterator);
            
        }
        
        //通过迭代器模式,我们只需要一个循环就可以实现那些list、数组、map等这些存储的遍历了
        public void printMenu(Iterator iterator){
            while(iterator.hasNext()){
                MenuItem menuItem = (MenuItem)iterator.next();
                System.out.println("名称:" + menuItem.getName() + ",介绍:" + menuItem.getDescription() + ",是否素菜:" +menuItem.isVegetarian() + ",价格:" + menuItem.getPrice());
            }
        }
    }

      好了让我们来编写测试类来进行测试下

    public class Test {
        public static void main(String[] args) {
            PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
            DinerMenu dinerMenu = new DinerMenu();
            
            //创建服务员,把菜单传给她
            Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
            
            //打印菜单
            waitress.printMenu();
        }
    }

      运行结果如下:

         

      这就是迭代器模式了,就不需要我们写那么多类似的for循环了。

      下一节:组合模式

    作者:哀&RT
    出处:博客园哀&RT的技术博客--http://www.cnblogs.com/Tony-Anne/
    您的支持是对博主最大的鼓励,感谢您的认真阅读。
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    第一次作业:了解编译原理
    DFA最小化,语法分析初步
    非确定的自动机NFA确定化为DFA
    正规式、正规文法与自动机
    正规文法与正规式
    词法分析程序的设计与实现
    文法和语言总结与梳理
    语法树,短语,直接短语,句柄
    理解文法和语文
    了解编译原理
  • 原文地址:https://www.cnblogs.com/Tony-Anne/p/6525513.html
Copyright © 2011-2022 走看看