迭代器模式(Iterator Pattern)

本文介绍迭代器模式的应用,通过示例展示如何使用该模式来遍历早餐和午餐菜单的项目,而不暴露内部存储结构。文章提供了C#实现的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 迭代器模式:让客户遍历你的对象而又无法窥视你存储对象的方式


场景:又一个早餐菜单和一个午餐菜单,使用迭代器模式将两个菜单打印出来。

//菜单创建迭代器的接口

    //类似工厂模式,子类需要实现创建枚举对象的方法
    public interface  Menu
    {
         IEnumerator createIterator();
    }

//菜单子项

    public class MenuItem
    {
        string name;
        string description;
        bool vegetarian;
        double price;

        public MenuItem(string name, string description, bool vegetarian, double price)
        {
            this.name = name;
            this.description = description;
            this.vegetarian = vegetarian;
            this.price = price;
        }

        public string getName()
        {
            return name;
        }

        public string getDescription()
        {
            return description;
        }

        public double getPrice()
        {
            return price;
        }

        public bool isVegetarian()
        {
            return vegetarian;
        }
    }



//早餐菜单

    public class PancakeHouseMenu :Menu
    {
        List<MenuItem> menuItems;
        public PancakeHouseMenu()
        {
            menuItems = new List<MenuItem>();

            addItem("K&B's薄煎饼早餐", "薄煎饼、氢弹、吐司", true, 2.99);

            addItem("薄煎饼早餐例餐", "薄煎饼带煎蛋、香肠", false, 2.99);

            addItem("蓝莓薄煎饼","薄煎饼、新鲜蓝莓、蓝莓糖浆",true,3.49);

            addItem("松饼", "松饼,可以选择蓝莓或草莓", true, 3.59);
        }

        public void addItem(string name, string description, bool vegetarian, double price)
        {
            MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
            menuItems.Add(menuItem);
        }

        public List<MenuItem> getMenuItems()
        {
            return menuItems;
        }
        //早餐菜单在LIST中,List本身支持获取枚举对象
        public IEnumerator createIterator()
        {
            return menuItems.GetEnumerator();
        }
    }
//午餐菜单

    public class DinerMenu : Menu, IEnumerator
    {
        const int MAX_ITEMS = 4;
        int numberOfItems = 0;
        MenuItem[] menuItems;
        int position = -1;

        public DinerMenu()
        {
            menuItems = new MenuItem[MAX_ITEMS];

            addItem("素食BLT", "(煎)培根、生菜&西红柿放在麦皮面包上",true,2.99);

            addItem("BLT", "培根、生菜&西红柿", true, 2.99);


        }

        public void addItem(string name, string description, bool vegetarian, double price)
        {
            MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
            if (numberOfItems >= MAX_ITEMS)
            {
                Console.WriteLine("对不起,菜单已经满了,不允许增加菜单了!");
            }
            else
            {
                menuItems[numberOfItems] = menuItem;
                numberOfItems++;
            }
        }

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

        public object Current
        {
            get 
            {
                if (position < numberOfItems)
                    return menuItems[position];
                else
                    return null;
            }
        }

        public bool MoveNext()
        {
            position++;
            if (position < numberOfItems)
            {
                return true;
            }
            else
            {
                return false;
            }
            
        }

        public void Reset()
        {
            position = 0;
        }
        //午餐继承并实现了IEnumerator的接口,自身便包含了枚举对象
        public IEnumerator createIterator()
        {
            return this;
        }


    }
//服务员输出菜单

    public class Waitress
    {
        Menu pancakeHouseMenu;
        Menu dinerMenu;

        public Waitress(Menu pancakeHouseMenu, Menu dinerMenu)
        {
            this.pancakeHouseMenu = pancakeHouseMenu;
            this.dinerMenu = dinerMenu;
        }

        public void printMenu()
        {
            IEnumerator pancakeIterator = pancakeHouseMenu.createIterator();
            IEnumerator dinerIterator = dinerMenu.createIterator();
            Console.WriteLine("MENU\n----\nBREAKFAST");
            printMenu(pancakeIterator);
            Console.WriteLine("\nLUNCH");
            printMenu(dinerIterator);
        }
        //利用C#对枚举的支持进行遍历
        private void printMenu(IEnumerator iEnumerator)
        {
            while (iEnumerator.MoveNext())
            {
                if (iEnumerator.Current != null)
                {
                    MenuItem menuItem = (MenuItem)iEnumerator.Current;
                    Console.Write(menuItem.getName() + ", ");
                    Console.Write(menuItem.getPrice().ToString() + " -- ");
                    Console.WriteLine(menuItem.getDescription());
                }
                else
                {
                    break;
                }

            }
        }
    }
//测试用例

        static void Main(string[] args)
        {
            Menu pancakeHouseMenu = new PancakeHouseMenu();
            Menu dinerMenu = new DinerMenu();
            Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
            waitress.printMenu();
            Console.ReadLine();
        }
//测试结果

总结:

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

2.把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。

扩展:

单一责任:一个类应该只有一个引起变化的原因。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值