C#設(shè)計模式實現(xiàn)之迭代器模式
前言:
迭代器模式平時用的不多,因為不管C#還是Java都已經(jīng)幫我封裝了,但是你是否知道平時經(jīng)常在用的東西本質(zhì)是怎么回事呢。
看完迭代器模式你就知道C# foreach循環(huán)是怎么實現(xiàn)的了,我的另一篇C# Foreach循環(huán)本質(zhì)與枚舉器就講解了foreach的本質(zhì),其中用到的就是迭代器模式。
按照慣例,例子走起。(寫了幾個小時瀏覽器崩潰,我看見在自動保存啊,結(jié)果沒內(nèi)容,再擼一遍精簡點的吧)
一、餐館合并菜單
現(xiàn)在有兩個餐館和并,其中一個餐館做早餐,一個做晚餐。他們都有自己管理菜單的方式,現(xiàn)在兩個餐館合并需要對菜單進行統(tǒng)一管理,先讓我來看看他們原來的樣子。
兩個菜單的菜單項都是一樣的
public class MenuItme { //名字 public string Name { get; set; } //描述 public string Description { get; set; } //是否素菜 public bool Vegetarian { get; set; } //價格 public double Price { get; set; } public MenuItme(string name, string description, bool vegetarian, double price) { Name = name; Description=description; Vegetarian = vegetarian; Price = price; } }
早餐菜單,使用List管理,不限制長度
public class BreakFastMenu { private List<MenuItme> menuItmes; public BreakFastMenu() { menuItmes = new List<MenuItme>(); AddItem("梅菜扣肉餅", "好吃", false, 7); //菜單項... } public void AddItem(string name, string description, bool vegetarian, double price) { MenuItme menuItme = new MenuItme(name, description, vegetarian, price); menuItmes.Add(menuItme); } public List<MenuItme> GetMenuItmes() { return menuItmes; } }
晚餐菜單,使用數(shù)組管理,限制長度為6
public class DinerMenu { static readonly int Max_Items = 6; private int numberOfImtes = 0; private MenuItme[] menuItmes; public DinerMenu() { menuItmes = new MenuItme[Max_Items]; AddItem("爆炒癩蛤蟆", "講究火候", false, 42); //菜單項... } public void AddItem(string name, string description, bool vegetarian, double price) { MenuItme menuItme = new MenuItme(name, description, vegetarian, price); if (numberOfImtes >= Max_Items) { Console.WriteLine("菜單已滿"); } else { menuItmes[numberOfImtes] = menuItme; numberOfImtes++; } } public MenuItme[] GetMenuItmes() { return menuItmes; } }
當兩個餐館合并后需要打印早餐和晚餐菜單給顧客用。
BreakFastMenu breakFastMenu = new BreakFastMenu(); List<MenuItme> breakFastMenus = breakFastMenu.GetMenuItmes(); DinerMenu dinerMenu = new DinerMenu(); MenuItme[] dinerMenus = dinerMenu.GetMenuItmes(); //打印早餐 for (int i = 0; i < breakFastMenus.Count; i++) { Console.WriteLine(breakFastMenus[i].Name); } //打印晚餐 for (int i = 0; i < dinerMenus.Length; i++) { Console.WriteLine(dinerMenus[i].Name); }
按照這種做法我們總是需要處理兩個菜單,如果要打印素食,那么也需要循環(huán)遍歷兩個菜單。
假如加入第三家餐廳合并,我們就需要循環(huán)處理三次,顯然這種方式會讓我們系統(tǒng)難以維護。
接下來看我們?nèi)绾芜M行改進
二、改進菜單實現(xiàn)
計模式就是要封裝變化的部分,很明顯,這里變化是:不同的集合類所造成的遍歷,我們?nèi)绾畏庋b遍歷集合
不管早餐還是晚餐我們都要用到中括號[ ] 來取菜單項,集合長度來限制長度。
現(xiàn)在我們要創(chuàng)建一個對象,將他稱為迭代器(Iterator),利用它來封裝“遍歷集合內(nèi)的每個對象的過程”。
對于List
Iterator iterator = breakFastMenu.CreateIterator(); while (iterator.HasNext) { MenuItme menuItme = iterator.Next(); }
對于數(shù)組
Iterator iterator = dinerFastMenu.CreateIterator(); while (iterator.HasNext) { MenuItme menuItme = iterator.Next(); }
現(xiàn)在兩個集合的遍歷都統(tǒng)一了,而這種方式正是迭代器模式。關(guān)于迭代器我們需要知道的第一件事情,就是它依賴于一個迭代器接口。
這個接口可能有HasNext()方法高數(shù)我們是否在這個集合中還有更多的元素。
Next()方法返回這個集合中的下一個對象。一旦我們有了這個接口,就可以為各種對象集合實現(xiàn)迭代器。
現(xiàn)在我們對晚餐菜單進行改造,首先我們需要定義一個迭代器接口
public interface Iterator { bool HasNext(); Object Next(); }
加入一個晚餐菜單迭代器
public class DinerMenuIterator : Iterator { MenuItme[] menuItmes; int position = 0; public DinerMenuIterator(MenuItme[] menuItmes) { this.menuItmes = menuItmes; } public bool HasNext() { //由于數(shù)組是固定長度,不僅要檢查數(shù)組,還要檢查指定位置是否為空,如果為空后面就沒有菜單項了 if (position >= menuItmes.Length || menuItmes[position] == null) return false; else return true; } public object Next() { MenuItme menuItme = menuItmes[position]; position++; return menuItme; } }
用迭代器改寫晚餐菜單
public class DinerMenu { static readonly int Max_Items = 6; private int numberOfImtes = 0; private MenuItme[] menuItmes; public DinerMenu() { menuItmes = new MenuItme[Max_Items]; AddItem("爆炒癩蛤蟆", "講究火候", false, 42); //菜單項... } public void AddItem(string name, string description, bool vegetarian, double price) { MenuItme menuItme = new MenuItme(name, description, vegetarian, price); if (numberOfImtes >= Max_Items) { Console.WriteLine("菜單已滿"); } else { menuItmes[numberOfImtes] = menuItme; numberOfImtes++; } } public Iterator CreateIterator() { return new DinerMenuIterator(menuItmes); } //public MenuItme[] GetMenuItmes() //{ // return menuItmes; //} }
同理我們?yōu)樵绮图尤氲?br />
public class BreakFastIterator: Iterator { List<MenuItme> menuItmes; int position = 0; public BreakFastIterator(List<MenuItme> menuItmes) { this.menuItmes = menuItmes; } public bool HasNext() { if (position >= menuItmes.Count) return false; else return true; } public object Next() { MenuItme menuItme = menuItmes[position]; position++; return menuItme; } }
用迭代器改寫早餐菜單
public class BreakFastMenu { private List<MenuItme> menuItmes; public BreakFastMenu() { menuItmes = new List<MenuItme>(); AddItem("梅菜扣肉餅", "好吃", false, 7); //菜單項... } public void AddItem(string name, string description, bool vegetarian, double price) { MenuItme menuItme = new MenuItme(name, description, vegetarian, price); menuItmes.Add(menuItme); } public Iterator CreateIterator() { return new BreakFastIterator(menuItmes); } //public List<MenuItme> GetMenuItmes() //{ // return menuItmes; //} }
好了,讓我們試一試迭代器工作情況
三、迭代器模式
經(jīng)過第二步我們基本已經(jīng)實現(xiàn)迭代器模式,最后我們再改良一下打印菜單,并對菜單進行統(tǒng)一接口的管理。
定義一個Menu接口
public interface Menu { Iterator CreateIterator(); }
讓早餐晚餐都實現(xiàn)Menu接口,并封裝一個新的菜單打印
public class NewMenu { Menu breakFastMenu; Menu dinerMenu; public NewMenu(Menu breakFastMenu, Menu dinerMenu) { this.breakFastMenu = breakFastMenu; this.dinerMenu = dinerMenu; } public void PrintMenu() { Iterator breakFastIterator = breakFastMenu.CreateIterator(); Console.WriteLine("新菜單--------早餐"); PrintMenu(breakFastIterator); Console.WriteLine("新菜單--------晚餐"); Iterator dinerIterator = dinerMenu.CreateIterator(); PrintMenu(dinerIterator); } private void PrintMenu(Iterator iterator) { while (iterator.HasNext()) { //取得下一個項 MenuItme menuItme = (MenuItme)iterator.Next(); Console.WriteLine(menuItme.Name); } } }
迭代器模式定義:
迭代器模式:提供一種方法順序訪問一個集合對象中的各個元素,而又不暴露其內(nèi)部的表示。
迭代器模式讓我們能游走于集合內(nèi)的每一個元素,而又不暴露其內(nèi)部的表示。
把游走的任務(wù)放在迭代器上,而不是集合上。這樣簡化了集合的接口和實現(xiàn),也讓責任各得其所。
總結(jié)
到此這篇關(guān)于C#設(shè)計模式實現(xiàn)之迭代器模式的文章就介紹到這了,更多相關(guān)C#迭代器模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#?計算DataTime的4種時間差的方法(相差天數(shù)、相差小時、相差分鐘、相差秒)
這篇文章主要介紹了C#?計算DataTime的4種時間差(相差天數(shù)、相差小時、相差分鐘、相差秒),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05C# ManagementObjectSearcher操作window案例詳解
這篇文章主要介紹了C# ManagementObjectSearcher操作window案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-08-08C#操作SQLite數(shù)據(jù)庫方法小結(jié)
這篇文章介紹了C#操作SQLite數(shù)據(jù)庫的方法,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-06-06C#實現(xiàn)文件操作(復(fù)制,移動,刪除)的方法詳解
File類提供了常見的文件操作函數(shù),包括復(fù)制、移動、刪除、創(chuàng)建快捷方式等,本文將通過一些簡單的示例為大家詳細講講具體的使用,希望對大家有所幫助2023-05-05