2013年7月14日 星期日

設計模式:組合模式 (Composite Pattern)

組合模式 (Composite Pattern),以下程式碼以 C# 為例

說明:
數個物件之間,呈現一種樹狀結構。物件之間可以組合。

範例:
一個線上購物商城,有A、B兩品牌,都有手機、筆電兩種商品。要產生商品選單。

希望達成如下的效果
static void Main(string[] args)
{
    CompositeMenu cm = new CompositeMenu("分類");

    CompositeMenu cm_A = new CompositeMenu("A品牌");
    cm_A.Add(new LeafMenuPhone("Android"));
    cm_A.Add(new LeafMenuNB("14吋"));
    cm_A.Add(new LeafMenuNB("15吋"));
    cm.Add(cm_A);

    CompositeMenu cm_B = new CompositeMenu("B品牌");
    cm_B.Add(new LeafMenuPhone("Android"));
    cm_B.Add(new LeafMenuNB("13吋"));
    cm_B.Add(new LeafMenuNB("14吋"));
    cm.Add(cm_B);

    CompositeMenu cm_sale = new CompositeMenu("特價區");
    CompositeMenu cm_A2 = new CompositeMenu("A品牌");
    LeafMenuNB leaf_nb_14 = new LeafMenuNB("超值14吋");
    LeafMenuNB leaf_nb_15 = new LeafMenuNB("超值15吋");
    cm_A2.Add(leaf_nb_14); // 新增超值14吋
    cm_A2.Add(leaf_nb_15); // 新增超值15吋
    cm_A2.Remove(leaf_nb_15); // 移除超值15吋
    cm_sale.Add(cm_A2);
    cm.Add(cm_sale);

    cm.Print(0);

    Console.Read();
}
執行結果: 
分類
-A品牌
--Android手機
--14吋筆電
--15吋筆電
-B品牌
--Android手機
--13吋筆電
--14吋筆電
-特價區
--A品牌
---超值14吋筆電

實現重點在於,節點能夠連接另一個節點或葉。

其餘程式碼
// 選單元件抽像介面
abstract class MenuComponent
{
    protected string name;

    public MenuComponent(string name)
    {
        this.name = name;
    }

    // 顯示資料
    public abstract void Print(int depth);
}

// 節點選單
class CompositeMenu : MenuComponent
{
    private List<MenuComponent> menu = new List<MenuComponent>();

    public CompositeMenu(string name)
        : base(name)
    {
    }

    // 新增
    public void Add(MenuComponent m)
    {
        menu.Add(m);
    }

    // 移除
    public void Remove(MenuComponent m)
    {
        menu.Remove(m);
    }

    public override void Print(int depth)
    {
        Console.WriteLine(new String('-', depth) + this.name);

        foreach (MenuComponent m in menu)
        {
            m.Print(depth + 1);
        }

    }
}

// 葉(手機)
class LeafMenuPhone : MenuComponent
{
    public LeafMenuPhone(string name)
        : base(name)
    {
    }

    public override void Print(int depth)
    {
        Console.WriteLine(new String('-', depth) + name + "手機");
    }
}

// 葉(筆電)
class LeafMenuNB : MenuComponent
{
    public LeafMenuNB(string name)
        : base(name)
    {
    }

    public override void Print(int depth)
    {
        Console.WriteLine(new String('-', depth) + name + "筆電");
    }
}

相關連結:設計模式整理列表

沒有留言:

張貼留言