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

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

Composite组合模式结构如下:

<?XML:NAMESPACE PREFIX = V /><?XML:NAMESPACE PREFIX = O />

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

首先,我们先分析对于一棵树所包含的部分,树干、树枝、树叶,其中树干可以看成一个树枝(就是粗了点)。那么我们就应该有两种类实现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<list.Count;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 <?XML:NAMESPACE PREFIX = ST1 />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《设计模式》中的那句话:单个对象和组合对象的使用具有一致性。当然也的确感觉到一点矛盾:对于叶子节点来说,不需要ArrayList和Add()Remove()应该不继承才对,当然如果在代码执行性能可以达到要求的情况下,简化一下编码实现复杂度也是挺好的一件事。

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

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

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

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

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

设计模式学习笔记(九)——Composite组合模式相关推荐

  1. 设计模式学习笔记九:原型模式(Prototype Pattern)

    1.概述     意图:我们将已经存在的对象作为原型,用户可以通过复制这些原型创建新的对象.     使用场合:当一个系统应该独立于产品的创建.构造和表示时,可以使用原型模式.在原型模式中,产品的创建 ...

  2. 设计模式学习笔记——享元(Flyweight)模式

    设计模式学习笔记--享元(Flyweight)模式 @(设计模式)[设计模式, 享元模式, flyweight] 设计模式学习笔记享元Flyweight模式 基本介绍 享元案例 类图 实现代码 Big ...

  3. 设计模式学习笔记——中介者(Mediator)模式

    设计模式学习笔记--中介者(Mediator)模式 @(设计模式)[设计模式, 中介者模式, Mediator] 设计模式学习笔记中介者Mediator模式 基本介绍 中介者案例 类图 实现代码 Me ...

  4. 设计模式学习笔记——单例(Singleton)模式

    设计模式学习笔记--单例(Singleton)模式 @(设计模式)[设计模式, 单例模式, Singleton, 懒汉式, 饿汉式] 设计模式学习笔记单例Singleton模式 基本介绍 单例案例 类 ...

  5. 设计模式学习笔记--享元(Flyweight)模式

    写在模式学习之前 什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方案,这就是软件模式:每一个模式描述了一个在我们程序设计中经常发生的问题,以及该问题的解决方案:当我们碰到模式 ...

  6. 设计模式学习笔记--Mediator 中介者模式

    我们知道面向对象应用程序是由一组为了提供某种服务而彼此交互的对象组成.当彼此引用的对象数量比较少时,此时对象之间就为直接交互(点对点).而当对象的数量增加时,这种直接交互会导致对象之间复杂的.混乱的引 ...

  7. 设计模式学习笔记--Flyweight享元模式

    Flyweight模式也叫享元模式,是由GoF提出的23种设计模式中的一种.Flyweight模式是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用,所以叫享元.   此模式解决的是由于大量 ...

  8. 设计模式(八)Composite(组合模式)

    @TOC Composite(组合模式):将对象组合成树形结构以表示"部分-整体"的层次结构.它使得客户对单个对象和复合对象的使用具有一致性. 结构 意图 将对象组合成树形结构以表 ...

  9. 设计模式笔记九:组合模式

    原文:http://www.runoob.com/design-pattern/ 少许个人理解,如有错误请指出.欢迎一起讨论. 组合模式(Composite Pattern) 又叫部分整体模式,是用于 ...

  10. 步步为营 .NET 设计模式学习笔记 九、Command(命令模式)

    概述 在软件系统中,"行为请求者"与"行为实现者"通常呈现一种"紧耦合".但在某些场合,比如要对行为进行"记录.撤销/重做.事务& ...

最新文章

  1. 高级特性(4)- 数据库编程
  2. Niagara 泵阀
  3. matlab 三维矩阵向量化,Matlab:向量化三维矩阵的工艺
  4. QT的QQmlNdefRecord类的使用
  5. SAP Spartacus的persist focus,触发map set的条件
  6. Xcode9学习笔记67 - 打印查看程序沙箱结构中常用的几个目录
  7. Java EE 7社区调查结果!
  8. JavaScript每日学习日记(2)
  9. LwIP应用开发笔记之十:LwIP带操作系统基本移植
  10. 超级玛丽地图java_超级玛丽3全关地图
  11. gevent的同步与异步
  12. vscode二次开发_vscode 扩展开发从入门到颈椎病康复
  13. c语言ntc程序,NTC热敏电阻程序.doc
  14. IBM GPFS并行文件系统
  15. 第七章——ICell的常用属性与方法
  16. 《C++新经典》第17章 并发与多线程
  17. SpringCloud OpenFeign 整合 logbook 实现链路日志
  18. QtCreator:missing separator. Stop.
  19. Android自定义底部带有动画的Dialog
  20. Error could not open `Ejdklibamd64jvm.cfg‘问题解决

热门文章

  1. javascript页面刷新与定时跳转页面
  2. python如何导入类里_Python导入模块中的所有类(98)
  3. html 元素换行_超文本标记语言的段落与换行显示!
  4. 数据结构与算法:十大排序算法之堆排序
  5. 案例-简介小米侧边栏(HTML、CSS)
  6. AWT_addKeyListener键盘监听事件(Java)
  7. 用python建云盘_实用的Python(3)超简单!基于Python搭建个人“云盘”
  8. react native 处理iOS和安卓系统文字
  9. 第十三章 线程安全与锁优化
  10. git常用命令(史上最经典)