組合模式-Composite pattern

設計模式

定義:物件以樹狀結構組合,做為表現出整體-部分的階層關係。

目的:用樹狀階層的方式來管理物件節點。

Component:節點介面,定義每個節點操作方法。

Composite:組合節點,衍生自Component,可包含其他節點。

Leaf:末端節點,衍生自Component,但不包含其他節點。

精神:物件樹。

優點:分層管理。

缺點:需要用其他的方法來分辨節點真正的類型。

使用時機:當物件很多,需要階層管理的時候或是出現出合成物件的樹狀結構,就可以使用。

舉例:早餐店的火腿起司蛋吐司,每個火腿起司蛋吐司有火腿、起司、煎蛋、沙拉、吐司,
           這些都算是材料,透過這些材料組合成火腿起司蛋吐司。

    class Program
    {
        private static void Main(string[] args)
        {
            Composite root = new Composite("root");
            root.Add(new Leaf("Leaf A"));
            root.Add(new Leaf("Leaf B"));

            Composite comp = new Composite("Composite X");
            comp.Add(new Leaf("Leaf XA"));
            comp.Add(new Leaf("Leaf XB"));

            root.Add(comp);
            root.Add(new Leaf("Leaf C"));

            Leaf leaf = new Leaf("Leaf D");
            root.Add(leaf);
            root.Remove(leaf);

            root.Display(1);
            Console.ReadKey();
        }
    }

    abstract class Component
    {
        protected string _name;

        protected Component(string name)
        {
            _name = name;
        }

        public abstract void Add(Component c);

        public abstract void Remove(Component c);

        public abstract void Display(int depth);
    }

    class Composite : Component
    {
        private List<Component> children = new List<Component>();

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

        public override void Add(Component c)
        {
            children.Add(c);
        }

        public override void Remove(Component c)
        {
            children.Remove(c);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + _name);
            foreach (Component component in children)
            {
                component.Display(depth + 2);
            }
        }
    }

    class Leaf : Component
    {
        public Leaf(string name) : base(name)
        {
        }

        public override void Add(Component c)
        {
            Console.WriteLine("Cannot add to a leaf");
        }

        public override void Remove(Component c)
        {
            Console.WriteLine("Cannot remove from a leaf");
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + _name);
        }
    }

來個中式餐點菜單案例,我麵有牛肉麵與乾麵、飯有咖哩飯、滷肉飯,這時候我就可以用組合模式如下:

   class Program
    {
        private static void Main(string[] args)
        {
 
            Composite hostMenu = new Composite("主菜單");
            Composite noodlesMenu = new Composite("麵類");
            noodlesMenu.Add(new LeafNoodles("牛肉麵"));
            noodlesMenu.Add(new LeafNoodles("乾麵"));
            hostMenu.Add(noodlesMenu);
            Composite riceMenu = new Composite("飯類");
            riceMenu.Add(new LeafRice("滷肉飯"));
            riceMenu.Add(new LeafRice("咖哩飯"));
            hostMenu.Add(riceMenu);
            hostMenu.Display(0);
        }
    }

    abstract class MenuComponent
    {
        protected string _name;

        protected MenuComponent(string name)
        {
            _name = name;
        }

        public abstract void Add(MenuComponent c);

        public abstract void Remove(MenuComponent c);

        public abstract void Display(int depth);
    }

     class Composite : MenuComponent
    {
        private List<MenuComponent> children = new List<MenuComponent>();

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

        public override void Add(MenuComponent c)
        {
            children.Add(c);
        }

        public override void Remove(MenuComponent c)
        {
            children.Remove(c);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + _name);
            foreach (MenuComponent component in children)
            {
                component.Display(depth + 2);
            }
        }
    }

     class LeafNoodles : MenuComponent
    {
        public LeafNoodles(string name) : base(name)
        {
        }

        public override void Add(MenuComponent c)
        {
        }

        public override void Remove(MenuComponent c)
        {
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + _name);
        }
    }

    class LeafRice : MenuComponent
    {
        public LeafRice(string name) : base(name)
        {
        }

        public override void Add(MenuComponent c)
        {
        }

        public override void Remove(MenuComponent c)
        {
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + _name);
        }
    }

 

 

元哥的筆記