组合模式的定义

组合模式允许你将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以一致的方式处理单个对象以及对象的组合。

组合模式实现的最关键的地方是——简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进行一致处理的原因。

  • Component抽象构件
          定义参加组合对象的共同方法和属性,可以定义一些默认的行为或属性。 
  • Leaf叶子构件
          叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。 
  • Composite树枝构件
         树枝对象,它的作业是组合树枝节点和叶子节点形成一个树形结构。
 
具体代码如下:
namespace ConsoleApplication1
{
    /// <summary>
    /// 抽象构件
    /// </summary>
    public abstract class Component
    {
        //个体和整体都具有的共享
        public virtual void doSomething()
        {
            //
        }
    }

    /// <summary>
    /// 树枝构件
    /// </summary>
    public class Composite : Component
    {
        //构件容器
        private List<Component> componentList = new List<Component>();
        //增加一个叶子构件或树枝构件
        public void Add(Component component)
        {
            componentList.Add(component);
        }
        //删除一个叶子构件或树枝构件
        public void remove(Component component)
        {
            componentList.Remove(component);
        }
        //获取分支下的所有叶子构件和树枝构件
        public List<Component> getChildren()
        {
            return this.componentList;
        }

        public override void doSomething()
        {
           
        }
    }
    /// <summary>
    /// 树叶构件
    /// </summary>
    public class Leaf : Component
    {
        //覆盖父类的方法
        public override void doSomething()
        {

        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //创建一个根节点
            Composite root = new Composite();
            root.doSomething();
            //创建一个树枝构件
            Composite branch = new Composite();
            //创建一个叶子节点
            Leaf leaf = new Leaf();
            //建立整体
            root.Add(branch);
            branch.Add(leaf);
            Console.ReadLine();
        }

        static void display(Composite root)
        {
            foreach (Component c in root.getChildren())
            {
                if (c is Leaf)
                {
                    //叶子节点
                    c.doSomething();
                }
                else
                {
                    //树枝节点
                    display((Composite)c);
                }
            }
        }
    }
}
View Code

组合模式的优缺点

优点:

  1. 组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。
  2. 将”客户代码与复杂的对象容器结构“解耦。
  3. 可以更容易地往组合对象中加入新的构件。

缺点:使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系。(这个是几乎所有设计模式所面临的问题)。

注意的问题:

  1. 有时候系统需要遍历一个树枝结构的子构件很多次,这时候可以考虑把遍历子构件的结构存储在父构件里面作为缓存。
  2. 客户端尽量不要直接调用树叶类中的方法(在我上面实现就是这样的,创建的是一个树枝的具体对象,应该使用Graphics complexGraphics = new ComplexGraphics("一个复杂图形和两条线段组成的复杂图形");),而是借用其父类(Graphics)的多态性完成调用,这样可以增加代码的复用性。

组合模式的使用场景

在以下情况下应该考虑使用组合模式:

  1. 需要表示一个对象整体或部分的层次结构。
  2. 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。