用心理解设计模式——组合模式 (Composite Pattern)

前置文章: 设计模式的原则 

其他设计模式:用心理解设计模式专栏

设计模式相关代码已统一放至 我的 Github

 

一、定义

  结构型模式之一。

  Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

  (将对象组合成树形结构以表示 “整体-部分” 的层次结构,组合模式使客户端对单个对象和组合对象的操作一致。)

二、结构解析

  组合模式的一般结构有三种角色: 抽象组件、叶节点、枝节点。

  抽象组件(Component):负责定义可供客户统一操作的接口方法。包含增加、移除子节点等必需的接口方法。

  叶节点(Leaf):继承抽象组件,对增加、移除子节点的接口方法给出空实现或抛出异常。重写其他接口方法,以支持对叶节点的特别操作。

  枝节点(Composite):继承抽象组件,聚合/持有一组抽象组件类型的成员,实际可接收叶节点或其他枝节点。真正实现增加、移除子节点的接口方法。重写其他接口方法,以支持针对枝节点的特别操作,常含有递归逻辑。

三、评价

  组合模式定义了一种 “整体包含部分,部分又可以包含整体” 的树状结构,客户可以对整体和部分统一对待。

  组合模式中,各节点的层级分明,扩展移除也非常容易。

  组合模式非常常见,如 文件夹和文件系统、Unity的Hierachy视图等。

  组合模式又分为 透明型组合模式安全型组合模式

  透明组合模式,即如上文 二 中描述的那样。

  安全型组合模式,与之不同的是:它在抽象组件中不再定义 “增加、移除子节点等接口方法”,这些方法只在枝节点类中扩展实现。优点是叶节点不再继承它不需要的一些接口方法,变得更安全。缺点是丧失了外部对枝和叶操作的一致性,需要在操作时先辨别是枝还是叶,再分别对待。

四、实现

  额外增加了depth属性,以说明层级分明,扩展移除也非常容易。

  实现结果预览(前缀的 “-” 数量代表其深度):

  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace Composite
{
    //抽象组件
    public abstract class Component
    {
        protected string name;  //名称

        public int depth = 0;   //自身深度

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

        public abstract void Add(Component component);

        public abstract void Remove(Component component);

        public abstract Component GetChild(int index);

        public abstract void RecurveShow();

        //-------------------下面是本设计模式的非主要方法----------------------
        public void Operate()
        {
            Debug.Log(GetDepthStr() + GetName());
        }

        public string GetDepthStr()
        {
            string depthStr = "";
            for (int i = 0; i < this.depth; i++)
            {
                depthStr += "- ";
            }
            return depthStr;
        }

        public string GetName()
        {
            return this.name;
        }

        public abstract void RefreshDepth(int depth);
    }

    //叶节点
    public class Leaf : Component
    {
        public Leaf(string name) : base(name) { }

        public override void Add(Component component)
        {
            throw new NotImplementedException();
        }

        public override void Remove(Component component)
        {
            throw new NotImplementedException();
        }

        public override Component GetChild(int index)
        {
            throw new NotImplementedException();
        }

        public override void RecurveShow()
        {
            this.Operate();
        }

        public override void RefreshDepth(int depth)
        {
            this.depth = depth;
        }
    }

    //枝节点
    public class Composite : Component
    {
        private List<Component> children = new List<Component>();

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

        public override void Add(Component component)
        {
            component.RefreshDepth(this.depth + 1);
            children.Add(component);
        }

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

        public override Component GetChild(int index)
        {
            return children[index];
        }

        public override void RecurveShow()
        {
            this.Operate();
            foreach (Component child in children)
            {
                child.RecurveShow();
            }
        }

        public override void RefreshDepth(int depth)
        {
            this.depth = depth;
            foreach (Component child in children)
            {
                child.RefreshDepth(this.depth + 1);
            }
        }
    }

    public class Client
    {
        static public void Main()
        {
            //创建根节点,并加入两个叶节点
            Composite root = new Composite("root");
            root.Add(new Leaf("LeafA"));
            root.Add(new Leaf("LeafB"));

            //创建带有叶节点的枝节点,最后加入根节点
            Composite compX = new Composite("CompositeX");
            compX.Add(new Leaf("LeafC"));
            compX.Add(new Leaf("LeafD"));
            compX.Add(new Leaf("LeafE"));
            compX.Remove((Leaf)compX.GetChild(1));
            root.Add(compX);

            //创建更深层的带有叶节点的枝节点,最后加入根节点
            Composite compY = new Composite("CompositeY");
            Composite compZ = new Composite("CompositeZ");
            compX.Add(compY);
            compY.Add(compZ);
            compZ.Add(new Leaf("LeafF"));
            
            //递归显示
            root.RecurveShow();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NRatel

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值