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)在兩個餐館合并需要對菜單進(jì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;
}
}
當(dāng)兩個餐館合并后需要打印早餐和晚餐菜單給顧客用。
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)難以維護(hù)。
接下來看我們?nèi)绾芜M(jìn)行改進(jìn)
二、改進(jìn)菜單實現(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)在我們對晚餐菜單進(jì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)迭代器模式,最后我們再改良一下打印菜單,并對菜單進(jì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),也讓責(zé)任各得其所。
總結(jié)
到此這篇關(guān)于C#設(shè)計模式實現(xiàn)之迭代器模式的文章就介紹到這了,更多相關(guān)C#迭代器模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實現(xiàn)對數(shù)組進(jìn)行隨機(jī)排序類實例
這篇文章主要介紹了C#實現(xiàn)對數(shù)組進(jìn)行隨機(jī)排序類,實例分析了C#數(shù)組與隨機(jī)數(shù)操作技巧,非常具有實用價值,需要的朋友可以參考下2015-03-03
C#使用Log4net實現(xiàn)將日志輸出到控制臺或者文本文檔
Log4net?是一個穩(wěn)定且功能豐富的日志庫,已經(jīng)存在多年并且被廣泛使用,這篇文章主要為大家介紹了如何使用Log4net實現(xiàn)將日志輸出到控制臺或者文本文檔,感興趣的可以了解下2024-03-03

