• 迭代器模式和组合模式(head first设计模式——8)


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

    一、迭代器模式

    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

  • 相关阅读:
    BZOJ 1051: [HAOI2006]受欢迎的牛( tarjan )
    BZOJ 2208: [Jsoi2010]连通数( DFS )
    js效果-鼠标提示框
    CSS-背景
    CSS-文本
    tomcat 安装 for Mac
    CSS选择器基础
    POJ3349-Snowflake Snow Snowflakes-Hash
    数据库的三大设计范式
    HDU5120-Intersection-两个圆环相交面积
  • 原文地址:https://www.cnblogs.com/lzhp/p/3427704.html
Copyright © 2020-2023  润新知