設計模式(14)---組合模式

1、定義安全

組合模式:將對象組合成樹形結構以表示「部分-總體」的層次結構。組合模式使得用戶對單個對象和組合對象的使用具備一致性。ide

解釋:簡單來講,編寫一個類,該類能做用於總體,而且編寫總體中的部分時也能使用該類,而不用作大的更改。this

 

2、UML類圖及基本代碼spa

基本代碼:設計

abstract class Component
    {
        protected string name;

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

        public abstract void Add(Component component);
        public abstract void Remove(Component component);
        public abstract void Display(int depth);
    }

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

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

        public override void Remove(Component component)
        {
            Console.WriteLine("cannot remove to a leaf");
        }

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

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

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

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

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

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

            foreach (Component component in children)
            {
                component.Display(depth + 2);
            }
        }
    }

 

客戶端進行調用:code

Composite root = new Composite("root");
            root.Add(new Leaf("leaf A"));
            root.Add(new Leaf("leaf B"));

            Composite composite = new Composite("Composite X");
            composite.Add(new Leaf("leaf XA"));
            composite.Add(new Leaf("leaf XB"));
            root.Add(composite);

            Composite composite2 = new Composite("Composite XY");
            composite2.Add(new Leaf("leaf XYA"));
            composite2.Add(new Leaf("leaf XYB"));
            composite.Add(composite2);

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

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

            root.Display(1);
View Code

結果如圖:component

 

3、透明方式和安全方式對象

  基本代碼中,leaf類也有add和remove方法,也就是說Component聲明全部用來管理子對象的方法,實現了全部子類都具有其方法的目的。這樣作的好處就是葉節點和枝節點對於外界沒有區別,它們具有徹底一致的行爲接口。但由於leaf不具有add和remove的功能,因此實現它是沒有意義的。這種方式就是透明方式。blog

  安全方式是葉節點和枝節點不具備相同的接口,因爲不夠透明,那麼客戶端調用時須要作相應的判斷,帶來了不便。因此在實際項目中使用安全方式和透明方式就須要視狀況而定。接口

 

4、舉例說明:

  繪製一個圖形,該圖形由一個複雜圖形和兩條線段組成。能夠自由的移除該圖形。

public abstract class Graphics
    {
        public string Name { get; set; }
        public Graphics(string name)
        {
            this.Name = name;
        }

        public abstract void Draw();
        public abstract void Add(Graphics graphics);
        public abstract void Remove(Graphics graphics);
    }

    public class Line : Graphics
    {
        public Line(string name)
            : base(name)
        { }

        public override void Draw()
        {
            Console.WriteLine("" + Name);
        }

        public override void Add(Graphics graphics)
        {
            throw new Exception("不能向簡單圖形line添加圖形");
        }

        public override void Remove(Graphics graphics)
        {
            throw new Exception("不能向簡單圖形line移除圖形");
        }
    }

    public class Circle : Graphics
    {
        public Circle(string name)
            : base(name)
        { }

        public override void Draw()
        {
            Console.WriteLine("" + Name);
        }

        public override void Add(Graphics g)
        {
            throw new Exception("不能向簡單圖形Circle添加其餘圖形");
        }
        public override void Remove(Graphics g)
        {
            throw new Exception("不能向簡單圖形Circle移除其餘圖形");
        }
    }

    public class ComplexGraphics : Graphics
    {
        private IList<Graphics> complexGraphicsList = new List<Graphics>();

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

        public override void Draw()
        {
            foreach (Graphics g in complexGraphicsList)
            {
                g.Draw();
            }
        }

        public override void Add(Graphics graphics)
        {
            complexGraphicsList.Add(graphics);
        }

        public override void Remove(Graphics graphics)
        {
            complexGraphicsList.Remove(graphics);
        }
    }

客戶端調用:

ComplexGraphics complexGraphics = new ComplexGraphics("一個複雜圖形和兩條線段組成的複雜圖形");
            complexGraphics.Add(new Line("線段A"));
            ComplexGraphics complexGraphics2 = new ComplexGraphics("一個圓和一條線組成的複雜圖形");
            complexGraphics2.Add(new Circle(""));
            complexGraphics2.Add(new Line("線段B"));
            complexGraphics.Add(complexGraphics2);
            Line line = new Line("線段C");
            complexGraphics.Add(line);

            Console.WriteLine("複雜圖形的繪製以下:");
            Console.WriteLine("----------------------");
            complexGraphics.Draw();
            Console.WriteLine("複雜圖形的繪製完成");
            Console.WriteLine("----------------------");

            complexGraphics.Remove(line);
            Console.WriteLine("移除線段C後,複雜圖形的繪製以下:");
            Console.WriteLine("---------------------");
            complexGraphics.Draw();
            Console.WriteLine("複雜圖形繪製完成");
            Console.WriteLine("---------------------");
View Code

調用結果:

 

5、優缺點及適用場景

優勢:

1)組合模式使得客戶端能夠一致的處理對象和對象容器,既是葉節點和枝節點。

2)更容易的爲組合對象添加新的組件。

3)解耦了客戶端與複雜對象。

缺點:

設計更加複雜。

 

適用場景:

1)須要表示一個對象總體和部分的層次結構

2)用戶但願忽略組合對象和單個對象的不一樣,一致的處理組合對象和單個對象。

相關文章
相關標籤/搜索