1. 程式人生 > >Head First設計模式——組合模式

Head First設計模式——組合模式

  最近比較忙,有段時間沒有更新設計模式的進度了。今天繼續學習組合設計模式。

  組合模式的例子我們繼續延續上篇《Head First設計模式——迭代器模式》的選單例子,首先宣告下迭代器和組合模式沒有什麼關係,他們是兩個不同模式。只是我們在這個選單例子的組合模式內部會用到迭代器。

迭代器模式中說到兩個餐館合併然後使用迭代器進行統一處理選單的列印,但是現在有一個新的需求是原來大選單中我們希望加入子選單,比如飯後甜點。那麼這個時候對於需求模型來說就是類似下面這樣

 

選單擁有選單項,選單項中可能還擁有子選單,我們現在要列印選單。也就是處理每個選單和選單項,如何將他們合理的組織起來並統一處理?要解決這個問題,組合模式來實現這一需求。

定義組合模式

組合模式:允許你將物件組合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理個別對象以及物件組合。

這個模式能夠建立一個樹形結構,如果我們有了一個樹形結構的選單、子選單和可能還帶有選單項的子選單,那麼任何一個選單都是一種“組合”。因為它既可以包含其他選單,也可以包含選單項。個別物件只是選單項並未持有其他物件。

利用組合設計選單

我們需要建立一個元件介面來作為選單和選單項的共同介面,讓我們能夠用統一的做法來處理選單和選單項,換句話說,我們可以針對選單或選單項呼叫相同的方法。

我們畫出選單設計的類圖:

 

MenuComponent:提供介面,讓選單項和選單共同使用。我們可能會對方法提供一些預設實現,所以我們可以使用抽象類。

MenuItem:繼承自MenuComponent,覆蓋了它有意義的方法(add,remove不用管)。

Menu:繼承自MenuComponent,覆蓋對它有意義的方法。

實現組合模式

 實現選單元件

    public abstract class MenuComponent
    {
        public virtual void Add(MenuComponent menuComponent) {
            throw new NotSupportedException();
        }
        public virtual void Remove(MenuComponent menuComponent)
        {
            throw new NotSupportedException();
        }
        public virtual MenuComponent GetChild(int i)
        {
            throw new NotSupportedException();
        }
        public virtual void GetName()
        {
            throw new NotSupportedException();
        }
        public virtual string GetDescription()
        {
            throw new NotSupportedException();
        }
        public virtual double GetPrice()
        {
            throw new NotSupportedException();
        }
        public virtual bool IsVegetarian()
        {
            throw new NotSupportedException();
        }
        public virtual void Print()
        {
            throw new NotSupportedException();
        }
    }

  實現選單項

    public class MenuItme : MenuComponent
    {
        string name;
        string decription;
        bool vegetarian;
        double price;

        public MenuItme(string name, string decription, bool vegetarian, double price)
        {
            this.name = name;
            this.decription = decription;
            this.vegetarian = vegetarian;
            this.price = price;
        }

        public override string GetName()
        {
            return name;
        }
        public override string GetDescription()
        {
            return decription;
        }
        public override double GetPrice()
        {
            return price;
        }
        public  override bool IsVegetarian()
        {
            return vegetarian;
        }
        public override void Print()
        {
            Console.Write(" " + GetName());
            if (IsVegetarian())
            {
                Console.Write("V" + GetName());
            }
            Console.WriteLine("," + GetPrice());
            Console.WriteLine("  --" + GetPrice());
        }
    }

  實現組合菜單

    public  class Menu:MenuComponent
    {
        List<MenuComponent> menuComponents = new List<MenuComponent>();
        string name;
        string description;
        public Menu(string name, string description)
        {
            this.name = name;
            this.description = description;
        }
        public override void Add(MenuComponent menuComponent)
        {
            menuComponents.Add(menuComponent);
        }
        public override void Remove(MenuComponent menuComponent)
        {
            menuComponents.Remove(menuComponent);
        }
        public override MenuComponent GetChild(int i)
        {
            return menuComponents[i];
        }
        public override string GetName()
        {
            return name;
        }
        public override string GetDescription()
        {
            return description;
        }
 
        public override void Print()
        {
            Console.Write("\n" + GetName());
            Console.WriteLine("," + GetDescription());
            Console.WriteLine("---------------------");
            foreach (var item in menuComponents)
            {
                item.Print();
            }
        }
    }

  這裡選單列印直接用foreach 迴圈列印選單元件,如果遇到另外一個選單物件則進入子選單列印。此處就是使用迭代器模式,只不過我偷了個懶直接用了foreach,因為list C#已經實現了迭代器,使用foreach語法即可。《C# Foreach迴圈本質與列舉器》

測試

    MenuComponent breakfastMenu = new Menu("早餐選單", "早餐供應");
    MenuComponent dinnerMenu = new Menu("晚餐選單", "晚餐供應");
    MenuComponent dessertMenu = new Menu("甜點選單", "晚餐甜點");

    MenuComponent allMenus = new Menu("ALL MENUS", "all menus combaind");
    //加入選單
    allMenus.Add(breakfastMenu);
    allMenus.Add(dinnerMenu);
    //加入選單項
    breakfastMenu.Add(new MenuItme("包子", "鮮肉醬肉", false, 2));
    dinnerMenu.Add(new MenuItme("牛肉拉麵", "拉麵配牛肉", false, 15));
    dinnerMenu.Add(dessertMenu);
    dessertMenu.Add(new MenuItme("夢龍捲", "切件", false, 16));

    allMenus.Print();

  

相關推薦

Head First設計模式讀書筆記八 第九章下 組合模式

組合模式+迭代器模式 接著上一節最後的例子,例子的最終list結構圖是這樣的: 若要給DinerMenu新加一種Menu(即下面這樣),則需要對現有結構進行較大改動。 可以看到,目前的結構中分為兩種結構,一種是menu,是一種容器,可以包含選單項,而第二種

迭代器模式組合模式-《Head First 設計模式

問題彙總 迭代器定義和作用 迭代器遍歷一個聚合物,並將其封裝成另一個物件。 迭代器適用場景 迭代器模式的結構和實現方法 組合模式定義和作用以及適用場景 適用於“整體/部分”的關係結構,用於統一處理所有物件(不分節點還是葉子)。 組合模式結構和實現的兩種方

Head First設計模式——組合模式

  最近比較忙,有段時間沒有更新設計模式的進度了。今天繼續學習組合設計模式。   組合模式的例子我們繼續延續上篇《Head First設計模式——迭代器模式》的選單例子,首先宣告下迭代器和組合模式沒有什麼關係,他們是兩個不同模式。只是我們在這個選單例子的組合模式內部會用到迭代器。

Head First 設計模式》:組合模式

# 正文 ## 一、定義 組合模式允許你將物件合成樹形結構來表現“整體/部分”層次結構。組合能讓客戶以一致的方式處理組合物件以及個體物件。 * 組合物件:包含其他元件的元件。 * 個體物件(葉節點物件):沒有包含其他元件的元件。 ![](https://img2020.cnblogs.com/blog

Head First 設計模式》學習筆記——復合模式

listener 解讀 out 部件 register != file 窗體 event 模型-視圖-控制器(MVC模式)是一種很經典的軟件架構模式。在UI框架和UI設計思路中扮演著很重要的角色。從設計模式的角度來看,MVC模式是一種復合模式。它將多個設計模式在

Head First設計模式之模板方法模式

names 去除 缺點 ide 個數 write ima 父類 public 一、定義 在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中,使得子類可以不改變算法結構的情況下,重定義該算法中的某些特定步驟。 比較通俗的說法,子類決定如何實現算法中的某些步驟,比如兩

Head First設計模式之外觀模式

實現 add ads important pac mar private 入口 summary 一、定義 外觀模式提供了一個統一的接口,用來訪問子系統中的一群接口。外觀定義了一個高層接口,讓子系統更容易使用。 外觀模式不只是簡化了接口,也將客戶從組件的子系統中解耦。

Head First設計模式之代理模式

collect prot indent margin 虛擬代理 ans sig smart ati 一、定義 定義:為其他對象提供一種代理以控制對這個對象的訪問 在代理模式中,我們創建具有現有對象的對象,以便向外界提供功能接口。 二、結構 代理模式一般會有三個角

Head First設計模式之享元模式(蠅量模式

logs sign face isp ria reat 定義 ogr sans 一、定義 享元模式(Flyweight Pattern)主要用於減少創建對象的數量,以減少內存占用和提高性能。這種類型的設計模式屬於結構型模式,它提供了減少對象數量從而改善應用所需的對象結構的

Head First設計模式之原型模式

webkit ble -1 否則 type sof 異常 構圖 etc 用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。 原型模式是一種比較簡單的模式,也非常容易理解,實現一個接口,重寫一個方法即完成了原型模式。在實際應用中,原型模式很少單獨出現。經常與其

Head First設計模式之狀態模式

對象狀態 initial fff rst actions arc sof ret %20 一、定義 定義:允許對象在內部狀態改變時改變它的行為, 對象看起來好像修改了它的類。 主要解決:對象的行為依賴於它的狀態(屬性),並且可以根據它的狀態改變而改變它的相關行為。 何

Head First設計模式之訪問者模式

back visitor 這樣的 耦合 擴展性 表示 accept struct system 一、定義 定義:表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素類的前提下定義作用於這些元素的新操作。 訪問者模式適用於數據結構相對穩定的系統, 它把數據結

Head First設計模式之中介者模式

函數 padding sta sin color 系列文章 自己的 技術 接口 一、定義 又稱為調停者模式,定義一個中介對象來封裝系列對象之間的交互。中介者使各個對象不需要顯示地相互引用,從而使其耦合性松散,而且可以獨立地改變他們之間的交互。 二、結構 組成:

Head First設計模式之解釋器模式

mes eval form value oid 對象 arc share hive 一、定義 給定一個語言,定義它的文法表示,並定義一個解釋器,這個解釋器使用該標識來解釋語言中的句子。 主要解決:對於一些固定文法構建一個解釋句子的解釋器。 何時使用:如果一種特定類型的

Head First設計模式之責任鏈模式

sre apple ria tap 空調 href 一個 -o webkit 一、定義   避免請求發送者與接收者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,並且沿著這條鏈傳遞請求,直到有對象處理它為止。   主要解決:職責鏈上的處理者負責處理請求,

Head First 設計模式》之裝飾者模式

的人 開放 override ext es2017 必須 想要 ret ted 前言:   時間過得挺快的,轉眼間就到了十月中旬了,再晃著晃著新的一年就要來臨。今天lz有幸來到了浙大圖書館來學習,想想自己已經畢業兩年了,今日再次踏進校園裏,心裏頗有一絲感悟,說不出來,只有把

Head first設計模式》學習筆記 – 叠代器模式

sys sorry 微軟雅黑 封裝 system ready 3.5 消息 all 《Head first設計模式》學習筆記 – 叠代器模式 代器模式提供一種方法順序訪問一個聚合對象中的各個元素,而又不暴露其內部的表示。 爆炸性新聞:對象村餐廳和對象村煎餅屋合並了!真是

Head First 設計模式“ :裝飾模式

裝飾模式 裝修模式 JAVAIO裝飾模式 裝飾模式 裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。 裝修模式的角色如下:抽象構件角色(Component):給出一個抽象接口,以規範準備接收附加責任的對象。具體構件角色(Concrete Com

Head First 設計模式“ :模板方法模式

設計模式 模板方法模式 模板方法 模板方法模式 定義:模板方法模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。模板方法就是一個固定步驟的“算法”骨架方法。這個算法的可變部分通過繼承,在子類中重載實現。這樣就可以

一句話的事兒,Head first 設計模式

因此 實例 模板方法模式 抽象方法 class 包裝 作用 自己的 定義 head first 設計模式,是比較有趣的一本設計模式的書。 在學校裏看書和在工作時看書,意義是不一樣的。在學校時是為讀書而讀書,我們可以從0到1,我們有的是時間。但是工作後就不一樣。 我覺得這時的