C#设计模式读书笔记之组合模式(Composite Pattern)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq826364410/article/details/87374873

组合模式(Composite Pattern)

1. 概述

  组合多个对象形成树形结构,以表示具有“整体-部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性。

组合模式的关键是定义了一个抽象组件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象组件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。同时容器对象与抽象组件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。

2. 模式中的角色

  2.1 抽象组件类(Component):它可以是接口或抽象类,为叶子组件和容器组件对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象组件类中,定义了访问及管理它的子组件的方法;

  2.2 叶子组件类(Leaf):在组合模式中,表示叶子节点对象,叶子节点没有子节点,实现了在抽象组件类中定义的行为。

  2.3 容器组件类(Composite):在组合模式中,表示容器节点对象,容器节点包含子节点,其子节点可以叶子节点,也可以是容器节点,提供了一个集合用于存储子节点,实现了在抽象组件类中定义的行为,包括访问及管理子组件的方法。

3. 模式解读

  3.1 模式的类图

       3.2 代码实现

现在以一个实际的例子用C#代码来实现,下面是Unity中的一个Hierarchy层级图,根节点是Root,下面有GameObject,GameObject (1), GameObject (2)三个节点,其中GameObject (1)下又有GameObject_A和GameObject_B两个节点:

using System;
using System.Collections.Generic;

namespace ConsoleApp2
{
    class Class14
    {
        public static void Main(string[] args)
        {
            DMComposite root = new DMComposite("Root");
            // 添加Root下的三个节点
            DMLeaf leaf1 = new DMLeaf("GameObject");
            DMLeaf leaf2 = new DMLeaf("GameObject (2)");
            DMComposite gameObject1 = new DMComposite("GameObject (1)");
            root.AddChild(leaf1);
            root.AddChild(gameObject1);
            root.AddChild(leaf2);

            // 添加GameObject (1)下面的两个节点
            DMLeaf child1 = new DMLeaf("GameObject_A");
            DMLeaf child2 = new DMLeaf("GameObject_B");
            gameObject1.AddChild(child1);
            gameObject1.AddChild(child2);

            // 按照广度优先或深度优先输出节点顺序
            //DepthFirstSearch(root);
            BreadthFirstSearch(root);

            Console.ReadLine();
        }

        // 广度优先检索
        private static void BreadthFirstSearch(DMComponent component)
        {
            Queue<DMComponent> q = new Queue<DMComponent>();
            q.Enqueue(component);
            Console.WriteLine(component.Name);
            while (q.Count > 0)
            {
                DMComponent temp = q.Dequeue();
                List<DMComponent> children = temp.Children;
                foreach (DMComponent child in children)
                {
                    Console.WriteLine(child.Name);
                    q.Enqueue(child);
                }
            }
        }

        // 深度优先检索
        private static void DepthFirstSearch(DMComponent component)
        {
            Console.WriteLine(component.Name);
            List<DMComponent> children = component.Children;
            if (children == null || children.Count == 0) return;
            foreach (DMComponent child in children)
            {
                DepthFirstSearch(child);
            }
        }

    }
    // 抽象组件类
    public abstract class DMComponent
    {
        protected string mName;
        public string Name { get { return mName; } }
        public DMComponent(string name)
        {
            mName = name;
            mChildren = new List<DMComponent>();
        }
        protected List<DMComponent> mChildren;
        public List<DMComponent> Children { get { return mChildren; } }
        public abstract void AddChild(DMComponent c);
        public abstract void RemoveChild(DMComponent c);
        public abstract DMComponent GetChild(int index);
    }

    // 叶子组件类
    public class DMLeaf : DMComponent
    {
        public DMLeaf(string name) : base(name) { }


        public override void AddChild(DMComponent c)
        {
            return;
        }

        public override void RemoveChild(DMComponent c)
        {
            return;
        }

        public override DMComponent GetChild(int index)
        {
            return null;
        }
    }

    // 容器组件类
    public class DMComposite : DMComponent
    {
        public DMComposite(string name) : base(name) { }


        public override void AddChild(DMComponent c)
        {
            mChildren.Add(c);
        }

        public override void RemoveChild(DMComponent c)
        {
            mChildren.Remove(c);
        }

        public override DMComponent GetChild(int index)
        {
            return mChildren[index];
        }
    }

}

广度优先搜索:

深度优先搜索:

4、 模式优缺点

4.1 优点

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。
  • 客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。
  • 定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。
  • 更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。

4.2 缺点

使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联

5、 模式适用场景

  • 需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。
  • 让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。
  • 用组合模式实现Unity中游戏物体父子关系的管理。

猜你喜欢

转载自blog.csdn.net/qq826364410/article/details/87374873