• 设计模式迭代器模式


    定义:

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

    理解:

    当访问一个聚合对象(ArrayList,Array)时,不管这些对象是什么时,都需要访问,这样可以考虑迭代器模式.

    或者当访问聚合对象有几个不同的方式时,也可以考虑使用迭代器模式

    实际上,遍历的行为可以理解为从第一个开始,查看下一个,是否还存在下一个.

    设计原则:

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

    关键词:

     Iterator

    结构图:

    image  

    例子:

    两个餐厅准备合并销售,一个餐厅负责早餐,一个餐厅负责午饭,但是两个餐厅存储菜单的方式不一致,导致服务员获取菜单后,还得自己进行分析才可以使用.如何能够使服务员不用对两个餐厅的菜单内容进行直接操作呢?现在看直接实现的结果,此结果导致服务员和两个餐厅的菜单相当耦合.

    菜单类:

    public class DfMenuItem
    {
        string name;
        string description;
        double price;
    
        public DfMenuItem(string name,string description,double price)
        {
            this.name = name;
            this.description = description;
            this.price = price;
        }
    
        public string GetName()
        {
            return this.name;
        }
    
        public string GetDescription()
        {
            return this.description;
        }
    
        public double GetPrice()
        {
            return this.price;
        }
    }
    
    
    早餐菜单类
    public class PancakHouseMenu
    {
        ArrayList al;
    
        public PancakHouseMenu()
        {
            al = new ArrayList();
    
            AddItem("Pancak1", "this is cake1", 11.0);
            AddItem("Pancak2", "this is cake2", 12.0);
            AddItem("Pancak3", "this is cake3", 13.0);
            AddItem("Pancak4", "this is cake4", 14.0);
        }
    
        private void AddItem(string name, string description, double price)
        {
            DfMenuItem dmi = new DfMenuItem(name, description, price);
            al.Add(dmi);
        }
    
        public ArrayList GetMenus()
        {
            return this.al;
        }
    
    }
    
    
    午餐菜单类:
    public class DinnerMenu
    {
        DfMenuItem[] dmis;
        int num = 0;
    
        public DinnerMenu()
        {
            dmis = new DfMenuItem[4];
            AddItem("Dinner1", "this is dinner1", 1.0);
            AddItem("Dinner2", "this is dinner2", 2.0);
            AddItem("Dinner3", "this is dinner3", 3.0);
            AddItem("Dinner4", "this is dinner4", 4.0);
        }
    
        private void AddItem(string name, string description, double price)
        {
            DfMenuItem item = new DfMenuItem(name, description, price);
            dmis[num] = item;
            num = num + 1;
        }
    
        public DfMenuItem[] GetMenus()
        {
            return this.dmis;
        }
    }
    
    ------------------------------------------------------------
    
    以上为两个已实现的类,下面是调用的方法:
    服务员类:
    public class Waitress
    {
        DinnerMenu dinnerMenus;
        PancakHouseMenu pancakesMenus;
        public Waitress(DinnerMenu dinnerMenus,PancakHouseMenu pancakesMenus)
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
            this.dinnerMenus = dinnerMenus;
            this.pancakesMenus = pancakesMenus;
        }
    
        public void PrintMenu()
        {
            PrintBreakFastMenu();
            PrintLunchMenu();
        }
    
        public void PrintBreakFastMenu()
        {
            DfMenuItem[] menus = dinnerMenus.GetMenus();
            for (int i = 0; i < menus.Length; i++)
            {
                HttpContext.Current.Response.Write(menus[i].GetDescription() + "<br/>");
            }
        }
    
        public void PrintLunchMenu()
        {
            ArrayList panlist = pancakesMenus.GetMenus();
            for (int i = 0; i < panlist.Count; i++)
            {
                HttpContext.Current.Response.Write(((DfMenuItem)panlist[i]).GetDescription()+"<br/>");
            }
        }
    }
    
    可以看到waitress类需要知道PancakMenus中菜单的实现方式,也需要知道dinnerMenus中菜单的实现方式
    ---------------------------------------------------------------
    
        protected void Button1_Click(object sender, EventArgs e)
        {
            DinnerMenu dinnerMenus = new DinnerMenu();
            PancakHouseMenu pancakeMenus = new PancakHouseMenu();
    
            WaiterTress wt = new WaiterTress(dinnerMenus,pancakeMenus);
            wt.PrintMenu();
        }
    
        protected void Button2_Click(object sender, EventArgs e)
        {
            DinnerMenu dinnerMenus = new DinnerMenu();
            PancakHouseMenu pancakeMenus = new PancakHouseMenu();
    
            WaiterTress wt = new WaiterTress(dinnerMenus, pancakeMenus);
            wt.PrintBreakFastMenu();
        }
    
        protected void Button3_Click(object sender, EventArgs e)
        {
            DinnerMenu dinnerMenus = new DinnerMenu();
            PancakHouseMenu pancakeMenus = new PancakHouseMenu();
    
            WaiterTress wt = new WaiterTress(dinnerMenus, pancakeMenus);
            wt.PrintLunchMenu();
        }
    此例子的缺点:
    如果再有一个用的存储方式发生变化的话,可能为影响到waitress的实现.
    修改两个Menu类.实现解耦.不让waitress对两个menu进行直接的实现.
    改变之后:
    public class DfMenuItem
    {
        string name;
        string description;
        double price;
    
        public DfMenuItem(string name,string description,double price)
        {
            this.name = name;
            this.description = description;
            this.price = price;
        }
    
        public string GetDescription()
        {
            return this.description;
        }
    }
    
    
    public class PancakHouseMenu
    {
        ArrayList al;
    
        public PancakHouseMenu()
        {
            al = new ArrayList();
    
            AddItem("Pancak1", "this is cake1", 11.0);
            AddItem("Pancak2", "this is cake2", 12.0);
            AddItem("Pancak3", "this is cake3", 13.0);
            AddItem("Pancak4", "this is cake4", 14.0);
        }
    
        private void AddItem(string name, string description, double price)
        {
            DfMenuItem dmi = new DfMenuItem(name, description, price);
            al.Add(dmi);
        }
    
        public IIterator CreateIterator()
        {
            return new PancakeIterator(al);
        }
    
    }
    
    
    public class DinnerMenu
    {
        DfMenuItem[] dmis;
        int num = 0;
    
        public DinnerMenu()
        {
            dmis = new DfMenuItem[4];
            AddItem("Dinner1", "this is dinner1", 1.0);
            AddItem("Dinner2", "this is dinner2", 2.0);
            AddItem("Dinner3", "this is dinner3", 3.0);
            AddItem("Dinner4", "this is dinner4", 4.0);
        }
    
        private void AddItem(string name, string description, double price)
        {
            DfMenuItem item = new DfMenuItem(name, description, price);
            dmis[num] = item;
            num = num + 1;
        }
    
        public IIterator CreateIterator()
        {
            return new DinnerIterator(this.dmis);
        }
    }
    
    
    public interface IIterator
    {
        bool HasNext();
    
        object Next();
    }
    
    public class DinnerIterator :IIterator
    {
        DfMenuItem[] items;
        int position = 0;
    
        public DinnerIterator(DfMenuItem[] items)
        {
            this.items = items;
        }
    
        #region IIterator 成员
    
        public bool HasNext()
        {
            if (position >= items.Length)
            {
                return false;
            }
    
            return true;
        }
    
        public object Next()
        {
            DfMenuItem item = items[position];
            position = position + 1;
            return item;
        }
    
        #endregion
    }
    
    public class PancakeIterator : IIterator
    {
        ArrayList al;
        int position;
    
        public PancakeIterator(ArrayList al)
        {
            this.al = al;
        }
    
    
        #region IIterator 成员
    
        public bool HasNext()
        {
            if (position >= al.Count)
            {
                return false;
            }
            return true;
        }
    
        public object Next()
        {
            return al[position++];
        }
    
        #endregion
    }
    
    -----------------------------------------------------------------
    
    public class WaiterTress
    {
        DinnerMenu dinnerMenus;
        PancakHouseMenu pancakesMenus;
        public WaiterTress(DinnerMenu dinnerMenus, PancakHouseMenu pancakesMenus)
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
            this.dinnerMenus = dinnerMenus;
            this.pancakesMenus = pancakesMenus;
        }
    
        public void PrintMenu()
        {
            PrintBreakFastMenu();
            PrintLunchMenu();
        }
    
        public void PrintBreakFastMenu()
        {
            Print(pancakesMenus.CreateIterator());
        }
    
        public void PrintLunchMenu()
        {
            Print(dinnerMenus.CreateIterator());
        }
    
        private void Print(IIterator iteraotr)
        {
            while (iteraotr.HasNext())
            {
                DfMenuItem item = iteraotr.Next() as DfMenuItem;
                HttpContext.Current.Response.Write(item.GetDescription() + "<br/>");
            }
        }
    }
    类图:
    image 

    优点:

     客户端不知道服务器端是如何存储数据,只需要调用就可以了.

    客户端无需管服务器段的数据存储是否发生变化,只需调用Iterator即可.此时,如果服务器端使用XML,文本,数据库来存储数据,均不会影响到客户端的引用.

    参考:

    《深入浅出设计模式》

    《大话设计模式》

  • 相关阅读:
    SpringCloud
    Linux
    SpringBoot
    秒杀系统设计
    设计模式
    数据库(mysql)
    Java web
    c#常用控件及简写
    C#常用的form窗体属性(最大化、最小化、窗体居中)
    C#中使用IndexOf()判断字符串在字符串数组中第一次出现的索引位置
  • 原文地址:https://www.cnblogs.com/oneword/p/1555215.html
Copyright © 2020-2023  润新知