迭代器模式和組合模式(head first設計模式——8)

把迭代器模式和組合模式放在同一篇的緣由是其聯繫比較緊密。算法

1、迭代器模式

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,晚餐類的結構是數組: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();
    }

}

迭代器模式主要是聚合對象建立迭代器,藉助單一職責的原則,從而實現客戶端能夠對聚合的各類對象實現相同的操做,達到代碼複用的效果。

1.3迭代器模式類圖

下面看看上面代碼的類圖,

image

而後再看看迭代器模式的類圖。

image

2、組合模式

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

相關文章
相關標籤/搜索