十、迭代器和组合模式

来源:互联网 发布:软件项目外包平台 编辑:程序博客网 时间:2024/05/16 08:34

把迭代器模式和组合模式放在同一篇的原因是其联系比较紧密。

一、迭代器模式

1.1迭代器模式定义

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

这个模式提供了一种方法,可以顺序访问一个聚合对象中的元素,而不用知道内部怎么表示的。为了更好的理解迭代器模式,我们举个例子。

1.2迭代器例子

下面使用head first设计模式中的例子,使用迭代器模式来演示早餐和晚餐菜单的显示。由于早餐和晚餐其数据结构不同,由于早餐店和晚餐店需要合并,所以需要一个统一的菜单:即菜单项结构相同。下面先介绍一下菜单项的结构。

复制代码
public class MenuItem    {        private string name;        private string description;        private bool vegetarin;        private double price;        public MenuItem(string name, string description, bool vegetarin, double price)        {            this.name = name;            this.description = description;            this.vegetarin = vegetarin;            this.price = price;        }        public string GetName()        {            return name;        }        public double GetPrice()        {            return price;        }        public bool IsVegetarian()        {            return vegetarin;        }        public string GetDescription()        {            return description;        }           }
复制代码

接下来分别来看一下早餐类和晚餐类,早餐类的结构是ArrayList,晚餐类的结构是数组:

复制代码
public class BreakfastMenu    {        ArrayList menuItems;        public BreakfastMenu()        {            menuItems = new ArrayList();            AddItem("牛奶", "牛奶description", false, 3.0);            AddItem("油条","油条description",false,1.0);            AddItem("馒头","馒头description",true,1.0);            AddItem("豆浆", "DoujiangDescription", true, 1.5);        }        public void AddItem(string name, string description, bool vegetarian, double price)        {            MenuItem menuItem = new MenuItem( name,  description,  vegetarian,  price);            menuItems.Add(menuItem);        }        public ArrayList GetMenuItems()        {            return menuItems;        }    }    public class DinerMenu    {        static readonly int Max_ITEMS = 6;        int numberOfItems = 0;        MenuItem[] menuItems;        public DinerMenu()        {            menuItems = new MenuItem[Max_ITEMS];            AddItem("香菇豆腐饭", "香菇豆腐", false, 10.5);            AddItem("蛋炒饭","哈哈",false,8.5);            AddItem("鱼香肉丝","你猜",true,15.5);        }        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;        }    }
复制代码

接下来看一下客户端是如何来把各种饭菜打印出来的:

复制代码
BreakfastMenu breakfastMenu = new BreakfastMenu();            ArrayList breakfastItems = breakfastMenu.GetMenuItems();            DinerMenu dinerMenu = new DinerMenu();            MenuItem[] lunchItems = dinerMenu.GetMenuItems();            for (int i = 0; i < breakfastItems.Count; i++)            {                MenuItem menuItem = breakfastItems[i] as MenuItem;                Console.WriteLine(menuItem.GetName()+" "+menuItem.GetPrice().ToString()+" "+menuItem.GetDescription().ToString());            }            for (int j = 0; j < lunchItems.Length; j++)            {                MenuItem lunchItem = lunchItems[j] ;                if (lunchItem!=null)                {                    Console.WriteLine(lunchItem.GetName() + " " + lunchItem.GetPrice().ToString() + " " + lunchItem.GetDescription().ToString());                }            }                        Console.ReadKey();
复制代码

很明显上面的遍历的算法是一样的,因为早餐和晚餐的数据结构的不同导致了代码不能复用,当然可以使用泛型解决该问题。但是本文需要使用的是迭代器设计模式。

为了可以使用相同的遍历方法,我们定义一个接口迭代器:

复制代码
public interface Iterator    {        /// <summary>        /// 用来判断下一个元素是否为空        /// </summary>        /// <returns></returns>         bool HasNext();        /// <summary>        /// 用来获取当前元素        /// </summary>        /// <returns></returns>         object Next();    }
复制代码

我们希望的是能通过迭代器实现下面的操作:

复制代码
while (iterator.HasNext())            {                MenuItem menuitem = (MenuItem)iterator.Next;                Console.WriteLine(menuitem.GetName() + " " + menuitem.GetPrice().ToString() + " " + menuitem.GetDescription().ToString());                            }
复制代码

接下来的目标就是创建早晚餐菜单的迭代器。

复制代码
public class BreakfastIterator : Iterator    {        private ArrayList items;        private int position;        public BreakfastIterator(ArrayList arrayList)        {            items = arrayList;        }        public bool HasNext()        {            if (position>items.Count||items[position]==null)            {                return false;            }            else            {                return true;            }        }        public object Next()        {            MenuItem menuItem = items[position] as MenuItem;            position = position + 1;            return menuItem;        }    }    public class DinnerIterator : Iterator    {        private MenuItem[] items;        private int position = 0;        public DinnerIterator(MenuItem[] items)        {            this.items = items;        }        public bool HasNext()        {            if (position > items.Length || items[position] == null)            {                return false;            }            else            {                return true;            }        }        public object Next()        {            MenuItem menuItem = items[position] as MenuItem;            position = position + 1;            return menuItem;        }    }
复制代码

可以定义一个菜单接口,来创建迭代器。分别让各个菜单去实现这个接口,下面给出完整的代码:

复制代码
using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace IteratorPattern{    class Program    {        static void Main(string[] args)        {            //BreakfastMenu breakfastMenu = new BreakfastMenu();            //ArrayList breakfastItems = breakfastMenu.GetMenuItems();            //DinerMenu dinerMenu = new DinerMenu();            //MenuItem[] lunchItems = dinerMenu.GetMenuItems();            //for (int i = 0; i < breakfastItems.Count; i++)            //{            //    MenuItem menuItem = breakfastItems[i] as MenuItem;            //    Console.WriteLine(menuItem.GetName() + " " + menuItem.GetPrice().ToString() + " " + menuItem.GetDescription().ToString());            //}            //for (int j = 0; j < lunchItems.Length; j++)            //{            //    MenuItem lunchItem = lunchItems[j];            //    if (lunchItem != null)            //    {            //        Console.WriteLine(lunchItem.GetName() + " " + lunchItem.GetPrice().ToString() + " " + lunchItem.GetDescription().ToString());            //    }            //}            IMenu breakfastMenu = new BreakfastMenu();            IMenu dinnerMenu = new DinnerMenu();            breakfastMenu.CreateIterator();            Iterator dinnerIterator = dinnerMenu.CreateIterator();            Iterator breakfastIterator = breakfastMenu.CreateIterator();            Print(breakfastIterator);            Print(dinnerIterator);            Console.ReadKey();        }        static void Print(Iterator iterator)        {            while (iterator.HasNext())            {                MenuItem menuItem = (MenuItem)iterator.Next();                Console.WriteLine(menuItem.GetName() + " " + menuItem.GetPrice().ToString() + " " + menuItem.GetDescription().ToString());            }        }    }    public class MenuItem    {        private string name;        private string description;        private bool vegetarin;        private double price;        public MenuItem(string name, string description, bool vegetarin, double price)        {            this.name = name;            this.description = description;            this.vegetarin = vegetarin;            this.price = price;        }        public string GetName()        {            return name;        }        public double GetPrice()        {            return price;        }        public bool IsVegetarian()        {            return vegetarin;        }        public string GetDescription()        {            return description;        }    }    public class BreakfastMenu : IMenu    {        ArrayList menuItems;        public BreakfastMenu()        {            menuItems = new ArrayList();            AddItem("牛奶", "牛奶description", false, 3.0);            AddItem("油条","油条description",false,1.0);            AddItem("馒头","馒头description",true,1.0);            AddItem("豆浆", "DoujiangDescription", true, 1.5);        }        public void AddItem(string name, string description, bool vegetarian, double price)        {            MenuItem menuItem = new MenuItem( name,  description,  vegetarian,  price);            menuItems.Add(menuItem);        }        public ArrayList GetMenuItems()        {            return menuItems;        }        public Iterator CreateIterator()        {            return new BreakfastIterator(menuItems);        }    }    public class DinnerMenu:IMenu    {        static readonly int Max_ITEMS = 6;        int numberOfItems = 0;        MenuItem[] menuItems;        public DinnerMenu()        {            menuItems = new MenuItem[Max_ITEMS];            AddItem("香菇豆腐饭", "香菇豆腐", false, 10.5);            AddItem("蛋炒饭","哈哈",false,8.5);            AddItem("鱼香肉丝","你猜",true,15.5);        }        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 Iterator CreateIterator()        {            return new DinnerIterator(menuItems);        }    }    public interface Iterator    {        /// <summary>        /// 用来判断下一个元素是否为空        /// </summary>        /// <returns></returns>         bool HasNext();        /// <summary>        /// 用来获取当前元素        /// </summary>        /// <returns></returns>         object Next();    }    public class BreakfastIterator : Iterator    {        private ArrayList items;        private int position;        public BreakfastIterator(ArrayList arrayList)        {            items = arrayList;        }        public bool HasNext()        {            if (position>=items.Count||items[position]==null)            {                return false;            }            else            {                return true;            }        }        public object Next()        {            MenuItem menuItem = items[position] as MenuItem;            position = position + 1;            return menuItem;        }    }    public class DinnerIterator : Iterator    {        private MenuItem[] items;        private int position = 0;        public DinnerIterator(MenuItem[] items)        {            this.items = items;        }        public bool HasNext()        {            if (position > items.Length || items[position] == null)            {                return false;            }            else            {                return true;            }        }        public object Next()        {            MenuItem menuItem = items[position] as MenuItem;            position = position + 1;            return menuItem;        }    }    public interface IMenu    {        Iterator CreateIterator();    }}
复制代码

迭代器模式主要是聚合对象创建迭代器,借助单一职责的原则,从而实现客户端可以对聚合的各种对象实现相同的操作,达到代码复用的效果。

1.3迭代器模式类图

下面看看上面代码的类图,

image

然后再看看迭代器模式的类图。

image

二、组合模式

2.1组合模式定义

组合模式允许将对象组合成属性结构来表现“整体/部分”层次结构,组合能让客户以一致的方式处理个别对象以及对象组合。

2.2组合模式例子

下面是组合模式的例子:

复制代码
class Program     {         static void Main(string[] args)         {             //定义早餐====================================================================             MenuComponent menu = new Menu("早餐", "新鲜的早餐");            MenuComponent menuItem1 = new MenuItem("牛奶", "牛奶description", false, 3.0);             MenuComponent menuItem2 = new MenuItem("油条", "油条description", false, 1.0);             MenuComponent menuItem3 = new MenuItem("馒头", "馒头description", true, 1.0);             MenuComponent menuItem4 = new MenuItem("豆浆", "DoujiangDescription", true, 1.5);                        menu.Add(menuItem1);             menu.Add(menuItem2);             menu.Add(menuItem3);             menu.Add(menuItem4);            //定义午餐====================================================================             MenuComponent lunch = new Menu("午餐", "包括下午茶");                         MenuComponent lunch1=new  MenuItem("香菇豆腐饭", "香菇豆腐", false, 10.5);             MenuComponent lunch2 = new MenuItem("蛋炒饭", "哈哈", false, 8.5);             MenuComponent lunch3 = new MenuItem("鱼香肉丝", "你猜", true, 15.5);             MenuComponent tea = new Menu("下午茶", "新鲜的下午茶");            MenuComponent tea1 = new MenuItem("香蕉片", "香蕉片", true, 10);             MenuComponent tea2 = new MenuItem("咖啡", "大杯的哦", true, 10);                         tea.Add(tea1);             tea.Add(tea2);            lunch.Add(lunch1);             lunch.Add(lunch2);             lunch.Add(lunch3);             lunch.Add(tea);            //定义三餐====================================================================             MenuComponent food = new Menu("三餐", "三餐列表");             food.Add(menu);             food.Add(lunch);             food.Print();             Console.ReadKey();         }    }    /// <summary>     /// 菜单组件     /// </summary>     public abstract class MenuComponent     {         public abstract void Add(MenuComponent menucomponent);        public abstract  void Remove(MenuComponent menucomponent);        public abstract MenuComponent GetChild(int i);        public abstract string GetDescription();        public abstract string GetName();        public abstract double GetPrice();        public abstract bool IsVegetarian();           public abstract void Print();     }    public class MenuItem:MenuComponent     {         private string name;         private string description;         private bool vegetarin;         private double price;        public MenuItem(string name, string description, bool vegetarin, double price)         {             this.name = name;             this.description = description;             this.vegetarin = vegetarin;             this.price = price;         }        public override  string GetName()         {             return name;         }        public override double GetPrice()         {             return price;         }        public override bool IsVegetarian()         {             return vegetarin;         }        public override string GetDescription()         {             return description;         }        public override void Print()         {             Console.Write(""+GetName()+",");             if (IsVegetarian())             {                 Console.Write("(素) ,");             }             Console.Write(GetPrice()+"¥,");             Console.WriteLine(GetDescription()+"");         }        public override MenuComponent GetChild(int i)         {             throw new NotImplementedException();         }        public override void Add(MenuComponent menucomponent)         {             throw new NotImplementedException();         }        public override void Remove(MenuComponent menucomponent)         {             throw new NotImplementedException();         }     }    public class Menu : MenuComponent     {         ArrayList menuComponents = new ArrayList();         private string name;         private string description;        public Menu(string name, string description)         {             this.name = name;             this.description = description;         }        public override void Add(MenuComponent menucomponent)         {             menuComponents.Add(menucomponent);             return;         }        public override void Remove(MenuComponent menucomponent)         {             menuComponents.Remove(menucomponent);         }        public override string GetName()         {             return name;         }        public override string GetDescription()         {             return description;         }        public override void Print()         {                         Console.Write("--"+GetName());             Console.WriteLine("," + GetDescription());            IEnumerator enumerator = menuComponents.GetEnumerator();             while (enumerator.MoveNext())             {                 MenuComponent menuComponent = (MenuComponent)enumerator.Current;                 menuComponent.Print();             }         }         public override MenuComponent GetChild(int i)         {             throw new NotImplementedException();         }         public override double GetPrice()         {             throw new NotImplementedException();         }        public override bool IsVegetarian()         {             throw new NotImplementedException();         }     }
复制代码

image

转载http://www.cnblogs.com/lzhp/p/3427704.html

0 0