热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

设计模式学习笔记(九)——Composite组合模式

Composite组合模式主要是应对这样的问题:一类具有“容器特征”的对象——即他们在充当对象的同时,又是其他对象的容器的情况。在编写时我们常常会造成:客户代码过多地依赖于对象容器复杂的内部实现,
 Composite 组合模式主要是应对这样的问题:一类具有“容器特征”的对象——即他们在充当对象的同时,又是其他对象的容器的情况。在编写时我们常常会造成:客户代码过多地依赖于对象容器复杂的内部实现,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性的弊端。

       GoF《设计模式》中说到:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得客户对单个对象和组合对象的使用具有一致性。

       Composite组合模式结构如下:



      
说道这,我觉得有一个编程中常见的场景,就是对于树的实现,很符合这个模式。下面我就用这个例子作一下。

       首先,我们先分析对于一棵树所包含的部分,树干、树枝、树叶,其中树干可以看成一个树枝(就是粗了点)。那么我们就应该有两种类实现Leaf(树叶)和Limb(树枝)。对于叶子节点和枝节点的不同在于枝节点有子树,而叶子节点没有子树。为了使单个对象和组合对象的使用具有一致性,我可以将叶子节点想象成没有子树的枝节点。这样我就可以得到一个抽象类,代码如下:

       public abstract class AbstractClass

    {

        public string name;

        public ArrayList list;

        public abstract void Add(AbstractClass item);       //增加一个子节点

        public abstract void Remove(AbstractClass item);    //去掉一个子节点

        public abstract string Print();                     //打印当前节点

    }

       然后,我在对叶子节点和枝节点作不同的实现:

       枝节点:

       public class Limb:AbstractClass

    {

        public Limb()

        {

            list = new ArrayList();

        }

 

        public override void Add(AbstractClass item)

        {

            list.Add(item);

        }

 

        public override void Remove(AbstractClass item)

        {

            if(list.Contains(item))

                list.Remove(item);

        }

        public override string Print()

        {

            Console.Write(name + "\n");

            if(list.Count != 0)

            {

                for(int i = 0;i

                {

                    Console.Write("(Parent is " + name + ")");

                    ((AbstractClass)list[i]).Print();

                }

            }

            return name;

        }

 

    }

    叶子节点:

    public class Leaf:AbstractClass

    {

        public Leaf()

        {

            list = null;

        }

 

        public override void Add(AbstractClass item)

        {

 

        }

        public override void Remove(AbstractClass item)

        {

           

        }

        public override string Print()

        {

            Console.Write(name + ",");

            return this.name;

        }

    }

    对于叶子节点来说,不需要子节点,当然也就不需要添加和删除子节点的方法。

    好,接下来,我们可以在客户程序中组建一棵树,来测试一下:

        static void Main (string[] args)

        {

            AbstractClass Tree = new Limb();

            GetTree(Tree);

            PrintTree(Tree);

            Console.Read();

        }

 

        public static void GetTree(AbstractClass Tree)

        {

            Tree.name = "1";

            AbstractClass leaf2 = new Leaf();

            leaf2.name = "2";

            Tree.Add(leaf2);

            AbstractClass limb3 = new Limb();

            limb3.name = "3";

            Tree.Add(limb3);

            AbstractClass leaf4 = new Leaf();

            leaf4.name = "4";

            limb3.Add(leaf4);

            AbstractClass leaf5 = new Leaf();

            leaf5.name = "5";

            limb3.Add(leaf5);

        }

 

        public static void PrintTree(AbstractClass Tree)

        {

            Tree.Print();

        }

    输出结果如下:

1

(Parent is 1)2,(Parent is 1)3

(Parent is 3)4,(Parent is 3)5,

在组织这个树时,的确能感觉到GoF《设计模式》中的那句话:单个对象和组合对象的使用具有一致性。当然也的确感觉到一点矛盾:对于叶子节点来说,不需要ArrayListAdd()Remove()应该不继承才对,当然如果在代码执行性能可以达到要求的情况下,简化一下编码实现复杂度也是挺好的一件事。

最后在来说说Composite组合模式的几个要点:

       1Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致的处理对象和对象容器,无需关心处理的是单个对象,还是组合的对象容器。

2、将“客户代码与复杂的对象容器结构”解耦是Composite模式的核心思想,解耦之后,客户代码将与纯粹的对象接口——而非对象容器的复杂内部实现结构——发生依赖关系,从而更能“应对变化”。

3Composite模式中,是将“AddRemove的和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在“表示对象容器的Composite类”中,是一个关乎“透明性”和“安全性”的两难问题,需要仔细权衡结构,这又是必须付出的代价。

4Composite模式在具体实现中,可以让父对象中的字对象反向追溯:如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率


推荐阅读
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • Ralph的Kubernetes进阶之旅:集群架构与对象解析
    本文深入探讨了Kubernetes集群的架构和核心对象,详细介绍了Pod、Service、Volume等基本组件,以及更高层次的抽象如Deployment、StatefulSet等,帮助读者全面理解Kubernetes的工作原理。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文详细探讨了Java中StringBuffer类在不同情况下的扩容规则,包括空参构造、带初始字符串和指定初始容量的构造方法。通过实例代码和理论分析,帮助读者更好地理解StringBuffer的内部工作原理。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 本文探讨了在Linux系统上使用Docker时,通过volume将主机上的HTML5文件挂载到容器内部指定目录时遇到的403错误,并提供了解决方案和详细的操作步骤。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 本文探讨了在 ASP.NET MVC 5 中实现松耦合组件的方法。通过分离关注点,应用程序的各个组件可以更加独立且易于维护和测试。文中详细介绍了依赖项注入(DI)及其在实现松耦合中的作用。 ... [详细]
author-avatar
Elaine桑定_148
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有