把迭代器模式和組合模式放在同一篇的緣由是其聯繫比較緊密。算法
迭代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而不是暴露其內部的表示。設計模式
這個模式提供了一種方法,能夠順序訪問一個聚合對象中的元素,而不用知道內部怎麼表示的。爲了更好的理解迭代器模式,咱們舉個例子。數組
下面使用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,晚餐類的結構是數組:ide
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; } }
接下來看一下客戶端是如何來把各類飯菜打印出來的:ui
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();
很明顯上面的遍歷的算法是同樣的,由於早餐和晚餐的數據結構的不一樣致使了代碼不能複用,固然可使用泛型解決該問題。可是本文須要使用的是迭代器設計模式。this
爲了可使用相同的遍歷方法,咱們定義一個接口迭代器:spa
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()); }
接下來的目標就是建立遲早餐菜單的迭代器。3d
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(); } }
迭代器模式主要是聚合對象建立迭代器,藉助單一職責的原則,從而實現客戶端能夠對聚合的各類對象實現相同的操做,達到代碼複用的效果。
下面看看上面代碼的類圖,
而後再看看迭代器模式的類圖。
組合模式容許將對象組合成屬性結構來表現「總體/部分」層次結構,組合能讓客戶以一致的方式處理個別對象以及對象組合。
下面是組合模式的例子:
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(); } }