组合模式(Composite)

目录

一、什么是组合模式?

1.1、Component(组件)

1.2、Leaf(叶子节点)

1.3、Composite(复合节点)

1.4、两种模式:

透明方式

安全方式

二、有什么优点?

三、有什么缺点?

四、什么时候适用?

五、代码展示

5.1、组合模式

5.2、Component类

5.3、Leaf类

5.4、Composite类


一、什么是组合模式?

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

组合模式(Composite)_第1张图片

1.1、Component(组件)

Component 是组合模式中的抽象基类或接口,用于声明叶子节点和复合节点共有的操作。它定义了叶子节点和复合节点都需要实现的方法,通常包括添加子节点、删除子节点、获取子节点等操作。Component 使得叶子节点和复合节点可以在相同的接口下进行操作,从而实现透明的组合。

1.2、Leaf(叶子节点)

Leaf 是组合模式中的叶子节点类,它表示树状结构中的最终节点,不能再包含子节点。Leaf 类实现了 Component 接口定义的操作,但在 Leaf 类中这些操作通常是空的,因为叶子节点没有子节点。Leaf 类代表了树状结构中的最小单元。

1.3、Composite(复合节点)

Composite 是组合模式中的复合节点类,它表示树状结构中的非叶子节点,可以包含子节点。Composite 类实现了 Component 接口定义的操作,并且包含一个子节点列表,用于管理其子节点。Composite 类代表了树状结构中的中间层次,它可以包含其他的叶子节点或复合节点。

举个例子,想象一个文件系统的场景。在这个场景中,Component 是文件和文件夹的抽象接口,Leaf 是文件类,而 Composite 是文件夹类。文件夹可以包含多个文件和其他文件夹,而文件本身是叶子节点,不能再包含其他内容。通过组合模式,你可以通过相同的方式处理文件和文件夹,使得对整个文件系统的操作变得一致和透明。

1.4、两种模式:

  • 透明方式

也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,他们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。

  • 安全方式

也就是在Component接口中不去声明Add()和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。

二、有什么优点?

  1. 统一接口: 组合模式通过让叶子节点和复合节点实现相同的接口,使得客户端可以统一地处理这些对象,无需关心它们的具体类型。

  2. 透明性: 对于客户端代码来说,无论是单个对象还是组合对象,都可以使用相同的方法进行操作,从而实现了透明性。

  3. 灵活性: 组合模式使得树状结构可以在运行时动态改变,可以很容易地增加、删除或替换节点,而不会影响其他部分的代码。

  4. 简化客户端代码: 由于统一了叶子节点和复合节点的接口,客户端代码无需关心对象的层次结构,从而简化了代码逻辑。

  5. 重用性: 通过组合模式,可以将操作应用于整个树状结构,从而提高了代码的重用性。

三、有什么缺点?

  1. 复杂性: 组合模式可能会引入一定的复杂性,特别是当树状结构变得很大或者层次很深时,管理和维护可能变得复杂。

  2. 不适合每个情况: 组合模式并不适用于所有情况,特别是当对象结构相对简单且层次不深时,引入组合模式可能会显得过于繁琐。

四、什么时候适用?

  1. 层次结构: 当你的对象具有层次结构,且需要以统一的方式进行操作时,可以考虑使用组合模式。例如,文件系统中的文件和文件夹。

  2. 部分-整体关系: 当你的对象之间存在部分-整体的关系,且需要一致地对待部分和整体时,组合模式非常有用。例如,图形界面中的 UI 组件。

  3. 树状结构: 当你需要构建树状结构的对象,且希望能够以统一的方式遍历和操作这些对象时,组合模式是一个很好的选择。

  4. 动态结构: 当对象结构可能在运行时发生变化,且需要灵活地添加、删除、替换节点时,组合模式可以提供很好的支持。

  5. 统一操作: 当你希望统一地处理单个对象和组合对象,从而避免使用繁琐的条件语句时,可以考虑使用组合模式。


五、代码展示

5.1、组合模式

组合模式(Composite)_第2张图片

5.2、Component类

//为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。
    //声明一个接口用于访问和管理Component的子部件
    abstract class Component
    {
        protected string name;         //成员变量
        public Component(string name) //有参构造方法
        {
            this.name = name;
        }

        //通常都用Add和Remove方法来提供增加或移除树叶或树枝的功能
        public abstract void Add(Component c);
        public abstract void Remove(Component c);
        public abstract void Display(int depth);
    }

5.3、Leaf类

//在组合中表示叶节点对象,叶节点没有子节点
    class Leaf : Component
    {
        public Leaf(string name) : base(name) { }
        public override void Add(Component c)
        {
            Console.WriteLine("Cannot add to a leaf");
        }

        public override void Remove(Component c)
        {
            Console.WriteLine("Cannot remove from a leaf");
        }

        public override void Display(int depth)
        {
            //叶节点的具体方法,此处是显示其名称和级别
            Console.WriteLine(new string('-', depth) + name);
        }
    }

5.4、Composite类

//定义有枝节点行为,用来存储子部件,在Component接口中
//实现与子部件有关的操作,比如增加Add和删除Remove
    class Composite : Component
    {
        //一个子对象集合用来存储其下属的枝节点和叶节点
        private List children = new List();
        public Composite (string name) : base(name) { }

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

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

        public override void Display(int depth)
        {
            //显示其枝节点名称,并对其下级进行遍历
            Console.WriteLine(new string('-', depth) + name);
            foreach(Component component in children)
            {
                component.Display(depth + 2);
            }
        }
    }

你可能感兴趣的:(设计模式,设计模式,组合模式)