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

一、迭代器模式

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 = ;
int numberOfItems = ;
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 = ; i < breakfastItems.Count; i++)
{
MenuItem menuItem = breakfastItems[i] as MenuItem;
Console.WriteLine(menuItem.GetName()+" "+menuItem.GetPrice().ToString()+" "+menuItem.GetDescription().ToString());
} for (int j = ; 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 + ;
return menuItem;
}
} public class DinnerIterator : Iterator
{
private MenuItem[] items;
private int position = ; 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 + ;
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 = ;
int numberOfItems = ;
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 + ;
return menuItem;
}
} public class DinnerIterator : Iterator
{
private MenuItem[] items;
private int position = ; 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 + ;
return menuItem;
}
} public interface IMenu
{
Iterator CreateIterator();
} }

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

1.3迭代器模式类图

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

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

二、组合模式

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, );
MenuComponent tea2 = new MenuItem("咖啡", "大杯的哦", true, ); 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();
}
}

迭代器模式和组合模式(head first设计模式——8)的更多相关文章

  1. 设计模式GOF23(结构型模式:代理模式,适配模式,桥接模式,组合模式,装饰模式,外观模式,享元模式)

    结构型模式: – 分类: • 适配器模式.代理模式.桥接模式.装饰模式.组合模式.外观模式.享元模式 – 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题.   结构 ...

  2. Java计模模式之六 ----- 组合模式和过滤器模式

    前言 在上一篇中我们学习了结构型模式的外观模式和装饰器模式.本篇则来学习下组合模式和过滤器模式. 组合模式 简介 组合模式是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来 ...

  3. java设计模式----迭代器模式和组合模式

    迭代器模式: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 设计原则: 单一责任:一个类应该只有一个引起变化的原因 组合模式: 允许你将对象组合成树形结构来表现“整体/部分” ...

  4. 《Javascript设计模式与开发实践》关于设计模式典型代码的整理:单例模式、策略模式、代理模式、迭代器模式、发布-订阅模式、命令模式、组合模式

    1.单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 使用闭包封装私有变量// 使用闭包创建单例var user = (function () { var _name = 'sven' ...

  5. 设计模式---数据结构模式之组合模式(Composite)

    前提:数据结构模式 常常有一些组建在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大的破坏组件的复用.这时候,将这些数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无 ...

  6. 设计模式16---设计模式之组合模式(Composite)(行为型)

    1.场景模拟 使用软件模拟大树的根节点和树枝节点和叶子节点 抽象为两类,容器节点和叶子节点 2.不用模式的解决方案 package demo14.composite.example1; import ...

  7. javascript设计模式----桥接模式、组合模式、装饰者模式、享元模式

    http://blog.csdn.net/painsonline/article/details/7215087    桥接模式:http://www.cnblogs.com/TomXu/archiv ...

  8. Java设计模式(8)——结构型模式之组合模式(Composite)

    一.概述 定义 将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. 简图 角色——对应上图中顶点为Component,左边为Leaf,右边为C ...

  9. GoF23种设计模式之结构型模式之组合模式

    一.概述 将对象组合成树型结构以表示“部分--整体”的层次关系.组合模式使得用户对单个对象和组合对象的使用具有一致性. 二.适用性 1.你想表示对象的部分--整体层次结构的时候. 2.你希望用户忽略组 ...

随机推荐

  1. 【Oracle 】tablespace 表空间创建和管理

    1.表空间的概述 1. 表空间是数据库的逻辑组成部分. 2. 从物理上讲,数据库数据存放在数据文件中: 3. 从逻辑上讲,数据库是存放在表空间中,表空间由一个或者多个数据文件组成. 2.oracle的 ...

  2. ASP.NET Core Linux环境安装并运行项目

    原文地址:https://blog.csdn.net/u014368040/article/details/79192622 一 安装环境 1.  从微软官网下载 Linux版本的.NetCoreSd ...

  3. list、map、数组 转换

    list,set,map,数组间的相互转换1.list转setSet set = new HashSet(new ArrayList()); 2.set转listList list = new Arr ...

  4. ReactNative 环境的搭建和启动(安卓版)

    一.JAVA环境 下载 JDK 8.0 添加 %JAVA_HOME% 变量 添加 PATH:%JAVA_HOME%\bin 二.Android环境 下载 Android SDK 修复 SDK Mana ...

  5. windows 环境使用 kafka

    近来学习 kafka,网上搜的教程好多不好用.在此开一贴记录一下学习过程.推荐官网,是最好的教程 http://kafka.apache.org/quickstart 官网上是linux 环境,我用的 ...

  6. Eclipse 快速提取一个方法 (重构)

    选择一块代码并将其转换为一个方法.Eclipse 会自动地推知方法参数及返回类型. 我们有的时候方法太大,但是自己复制粘贴重构又比较麻烦 eclispe拥有这个功能 alt+shift+m 也可以右键 ...

  7. AWS & ASP.NET

    https://dotnetcodr.com/amazon-cloud/ Amazon cloud Big Data overall architecture Architecture of a Bi ...

  8. Android 抓包并通过 Wireshark 分析

    分析 Android 中 app 的网络数据交互,需要在 Android 上抓包,常用工具为 tcpdump ,用 tcpdump 生成 Wireshark 识别的 pcap 文件,把 pcap 文件 ...

  9. C语言浮点数存储结构

    float类型占四个字节,每个字节占8位,总共32位,其内存结构如下图: 31位为符号位:0表示正数,1表示负数 31~23位:共8位表示指数位,内存存储数据从0~2^8-1=255,由于指数可以是正 ...

  10. LeetCode 326 Power of Three(3的幂)(递归、Log函数)

    翻译 给定一个整型数,写一个函数决定它是否是3的幂(翻译可能不太合适-- 跟进: 你能否够不用不论什么循环或递归来完毕. 原文 Given an integer, write a function t ...