Composite pattern和树

一切从,那一段代码开始的

     开始我们考虑这样一个问题,就是假定我们要写一个方法来遍历一个目录里所有的文件。因为目录里面可能还含有子目录,我们可能就需要用到循环,递归等这样的思路。一个典型的思路如下:

1. 首先列出该文件夹里所有内容。

2. 遍历里面所有的元素,如果该元素为纯文件,则显示文件名;否则,则递归调用该函数。

按照以上的思路,可以写出如下的一段简单的代码:

 

void listDirectory(String directory)
{
      File dir = new File(directory);
      for(File file : dir.listFiles())
      {
           if(!file.isDirectory())
               System.out.println(flie.getName());
           else
               listDirectory(file.getAbsolutePath());
      }
}

换个角度看问题

      前面那个问题的解决思路其实是基于这么一点。我们要遍历一个目录结构,因为目录里面可以有子目录和文件,从我们学习过的书本知识可以知道,这是一个树的结构。所以,我们可以通过这么一种递归的方式来访问所有的元素。因为是树,如果利用一些数据结构的知识,还可以整理出各种遍历元素的方法。这种思路也没什么不好的,现在,我们再换一种思路去想想。

      我们要访问的目录可以说是一个容器,它里面可以包含子容器和一些元素。这些子容器呢,也可以包含更下面一级的子容器以及元素,于是乎,子子孙孙无穷匮也...再从这个思路做进一步的延伸,也就是说,我们需要设计一个结构,这个结构可以包含它自身这种类型以及它的单个元素类型。最关键的一点就是,假定我是一个容器,我里面的元素可以是一层一层套的。于是这就引出了这么一种设计,composite pattern.

我们先看看它的类图:

 

Composite pattern和树_第1张图片

这个类图中间最取巧的一点就在于Composite这个类和Component类之间的关系。Composite首先和它有一个继承关系。另外一个Leaf类和Component也是同样的继承关系。另外,Composite与Component有一个可能的1对多的聚合或者组合关系。这意味着我一个Composite类可以包含有多个Component对象。因为前面提到的继承关系,所以我包含的可以是具体的Leaf对象,也可以是Composite对象。看到没?在这里,我们就引出了一个Composite可以包含有Composite关系的设计来了。和前面提到的我们一个目录可以包含另外一个目录,或者一个容器包含另外一个容器的说法是不是一样的呢?

牵一发而动全身

    实际上,如果我们可以对目录和文件做建模的话,可以做一个类似与如下的设计。我们可以定义一个抽象的File类,然后定义具体的ConcreteFile和Directory类来继承它。借鉴Composite pattern的思路,可以设计成如下图:

Composite pattern和树_第2张图片

这个设计的具体实现代码就不赘述,其中的关节点就在于Composite类里面对displayName方法的实现。因为是一个组合类,它这个方法的实现方式类似如下:

 

public void displayName()
{
        for(File file : getChild())
            file.displayName();
}

 它相当于将自己的方法又委托给自己的子元素了。

这种手法还有一个好处就是,当我们使用的时候,似乎只是针对一个File对象调用了displayName的方法,实际上它内部是针对所有的元素作了遍历的,可谓牵一发而动全身。

两种思路的区别

    我们现在回过头来看前面两种遍历的思路。其实第一种是将树中间的元素作了区分,需要在代码里判断是否为目录,如果为普通文件则显示名字,否则就要递归调用。至少在代码里,我们是需要用if else这样的代码来做个区分的。而第二种思路由于通过继承,我们可以说处理的都是Component,利用面向对象的特性,不需要用if else来判断了。从使用的角度来说看起来composite和leaf之间是相互可替换的。因为他们从component这个角度来说是一样的。

 

和Decorator Pattern之间的相似点以及区别

        如果我们前面看到过Decorator pattern的话,第一感觉会觉得他们两个模式之间关系比较密切,看起来差别不大。下面是decorator pattern的类图:

Composite pattern和树_第3张图片

其实,他们的差别主要在一下几个方面:

1:Decorator pattern主要是针对一个对象进行多重包装,所以其中的decorator和component之间基本上是1对1的关系。而composite pattern主要是体现出一个1对多的关系,更多的体现出层级的结构化。

2: Decorator pattern需要对一个decorator来继承出若干包装类,而composite不体现出要在原有元素的基础上进行什么特性的修改或增强,只是一个纯粹的对象组合,所以它的composite类就没有定义任何继承。

你可能感兴趣的:(Pattern)