设计模式(14)---组合模式

一、定义

组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

解释:简单来说,编写一个类,该类能作用于整体,并且编写整体中的部分时也能使用该类,而不用做大的更改。

 

二、UML类图及基本代码

基本代码:

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);
            }
        }
    }

 

客户端进行调用:

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

结果如图:

 

三、透明方式和安全方式

  基本代码中,leaf类也有add和remove方法,也就是说Component声明所有用来管理子对象的方法,实现了所有子类都具备其方法的目的。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但因为leaf不具备add和remove的功能,所以实现它是没有意义的。这种方式就是透明方式。

  安全方式是叶节点和枝节点不具有相同的接口,由于不够透明,那么客户端调用时需要做相应的判断,带来了不便。所以在实际项目中使用安全方式和透明方式就需要视情况而定。

 

四、举例说明:

  绘制一个图形,该图形由一个复杂图形和两条线段组成。可以自由的移除该图形。

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

调用结果:

 

五、优缺点及适用场景

优点:

1)组合模式使得客户端可以一致的处理对象和对象容器,既是叶节点和枝节点。

2)更容易的为组合对象添加新的组件。

3)解耦了客户端与复杂对象。

缺点:

设计更加复杂。

 

适用场景:

1)需要表示一个对象整体和部分的层次结构

2)用户希望忽略组合对象和单个对象的不同,一致的处理组合对象和单个对象。

 

posted @ 2014-11-28 09:56  小项目笔记  阅读(565)  评论(0编辑  收藏  举报

更多文章请关注公众号:小项目笔记

小项目笔记