2013年9月25日 星期三

設計模式 (四) Composite Pattern

通常會用到composite pattern都是在資料為樹狀圖時才會用到它
他的做法是將聚合元素(枝)與單一元素(葉) 視為同一個東西 (繼承同一個物件)
這樣的好處是當新增其他的葉時並不需要修改其他的class
先示範較不好的範例
他的缺點是當有新的葉class要做新增時例如希望新增 BCounty的時候對於bnation來說需要做大量的修改才能順利加BCounty加入
     
    class BRoot
    {
        private string name;
        private List<bnation> Nations = new List<bnation>();
        public BRoot(string name)
        {
            this.name = name;
        }
        public void Add(BNation b)
        {
            Nations.Add(b);
        }

        public void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
            foreach (var Nation in Nations)
            {
                Nation.Display(depth + 3);
            }
        }

    }
    class BNation
    {
        private string name;
        private List<bcity> Cities = new List<bcity>();
        public BNation(string name)
        {
            this.name = name;
        }

        public void Add(BCity b)
        {
            Cities.Add(b);
        }

        public void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
            foreach (var city in Cities)
            {
                city.Display(depth + 3);
            }
        }
    }
    class BCity
    {
        private string name;
        public BCity(string name)
        {
            this.name = name;
        }
        public void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + " city " + name);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            BRoot root = new BRoot("Root");
            BNation BChina = new BNation("China");
            BNation BTaiwan = new BNation("Taiwan");
            
            BChina.Add(new BCity("Ba Jin"));
            BChina.Add(new BCity("Su Jou"));                       
            BTaiwan.Add(new BCity("Taipei"));
            BTaiwan.Add(new BCity("Tainan"));

            root.Add(BChina);
            root.Add(BTaiwan);
            root.Display(0);

            Console.WriteLine();
        }
   }
Result:
Root
---China
------ city Ba Jin
------ city Su Jou
---Taiwan
------ city Taipei
------ city Tainan

正確的範例如下
當需要增加BCounty的時候  就如同增加BCity一樣 新增一個class就可以完成
新的修改並不會對舊有的code造成修改
    
    abstract class Component
    {
        protected string name;

        // Constructor
        public Component(string name)
        {
            this.name = name;
        }

        public abstract void Add(Component c);
        public abstract void Remove(Component c);
        public abstract void Display(int depth);
    }
    class Nation : Component
    {
        private List<component> Nations = new List<component>();
        public Nation(string name)
            : base(name)
        {
        }

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

        public override void Remove(Component c)
        {
            throw new NotImplementedException();
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
            foreach (Component City in Nations)
            {
                City.Display(depth + 3);
            }
        }
    }
    class City : Component
    {
        public City(string name)
            : base(name)
        {
        }

        public override void Add(Component c)
        {
            throw new NotImplementedException();
        }

        public override void Remove(Component c)
        {
            throw new NotImplementedException();
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + " city " + name);
            //throw new NotImplementedException();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Nation Root = new Nation("Root");
            Nation China = new Nation("China");
            Nation Taiwan = new Nation("Taiwan");
            
            China.Add(new City("Ba Jin"));
            China.Add(new City("Su Jou"));
            Taiwan.Add(new City("Taipei"));
            Taiwan.Add(new City("Tainan"));

            Root.Add(Taiwan);
            Root.Add(China);
            Root.Display(0);
        }
     }
Result:
Root
---Taiwan
------ city Taipei
------ city Tainan
---China
------ city Ba Jin
------ city Su Jou

沒有留言:

張貼留言