Composite模式带给我的只有Array有什么优势?

时间:2009-08-10 11:19:17

标签: php design-patterns

我最近正在研究树结构,多个节点,多个且可增加的级别以及print()方法。 起初,我认为它应该是一个复合词,然后我写下了一些可能的设计和代码:

alt text

$struc = new Node(‘name0’, ‘id0’, ‘desc0’);
$node1 = new Node(‘node1’, ‘id1’, ‘desc1’);
$node2 = new Node(‘node2’, ‘id2’, ‘desc2’);
$node3 = new Node(‘node3’, ‘id3’, ‘desc3’);
$leaf1 = new Leaf(‘leaf1’, ‘ld1’, ‘lesc1’);
$leaf2 = new Leaf(‘leaf2’, ‘ld2’, ‘lesc2’);
$leaf3 = new Leaf(‘leaf3’, ‘ld3’, ‘lesc3’);
$leaf4 = new Leaf(‘leaf4’, ‘ld4’, ‘lesc4’);

$struc.add($node1);
$struc.add($node3);

$node1.add($leaf1);
$node1.add($leaf2);
$node1.add($node2);

$node2.add($leaf3);    
$node3.add($leaf4);

看起来不错,我认为并开始编码,print()方法可能会遵循Iterator模式。 但在编码过程中,我觉得这些简单的节点太复杂了吗?而且我必须实例化很多具体的类(超过50多个,并且不断增加)。然后,我通过使用数组停止并思考一个简单的类似方法:

-- Structure Class --
//To be more readable and clear, array here could be
//divided to 3 arrays(root/nodes/leafs), then connect
//in a similar way Composite does.
$struc = array('name0', 'id0', 'desc0',

           'children'=>array(

               array('node1', 'id1', 'desc1',
                  'children' => array(
                     array('leaf1', 'ld1', 'lesc1'),
                     array('leaf2', 'ld2', 'lesc2'),
                     array('node2', 'id2', 'desc2',
                        'children'=>array(array('leaf3', 'ld3', 'lesc3'))
                     )
                  )
               ),

               array('node3', 'id3', 'desc3',
                  'children' => array(array('leaf4', 'ld4', 'lesc4'))
               )
           )
);

function print($node = $this->struct) {
    ...
    if(isset($node['children'])) $this->print($node['children']);
    ...
}

两个设计看起来非常相似,现在我有点困惑,复合模式的价值是什么,我错过了这个模式的重要部分吗?

3 个答案:

答案 0 :(得分:7)

复合的价值在于你交易一些复杂性以便能够不破解封装

在你的数组版本中,你正在打破封装 测试节点是否不是叶子:

if(isset($node['children'])) $this->print($node['children']);

使用复合材料,您可以说:

print();

然后运行时多态将调用正确的方法。在这种情况下(我不是PHP程序员,所以让我使用类似Java的语法):

class Node {

   void print() {
       for (child in children) {
          child.print();
       } 
   }

   ...
}

class Leaf {

   void print() {
       // print it! 
   }
}

与普通数组相比的另一个优势是你隐藏你的实现细节(数据结构等)

答案 1 :(得分:6)

composite pattern的要点是能够将对象集合视为单个对象(例如,用于显示或将其写入文件)。当你自己写“print()方法可能会跟随Iterator模式” - 好吧,复合模式的要点是你可以调用print()而不必担心你是打印单个Component还是必须迭代通过整个树。

但是看起来你似乎不清楚面向对象编程,因为你正在考虑使用嵌套数组。使用对象而不是散列(PHP数组是)的所有内容的值是type safety,这使得调试和维护程序变得更加容易。

答案 2 :(得分:0)

阵列实现看起来不是很复杂吗?如果我正在看它,我必须仔细研究它,以了解你在做什么。您正在处理索引,将条目分配给特定索引等......它看起来非常复杂。

当您查看正在使用它的代码时,您在其他网站上实现复合模式看起来很简单。您有一个节点,并将其他节点或叶子附加到该节点。没有什么复杂的,奇怪的,我不必关心/记住索引等...这就是复合模式在你的情况下有用的原因。当然,如果你不熟悉它,它的实现可能看起来有点复杂,但重要的一点(正如其他说明的那样)是你隐藏细节。这非常重要非常。这是一个简单的例子,它仍然适用于您的数组,但是当您在生产环境中实现此类代码时,其他开发人员可能也在编辑/维护您的代码。如果有人必须修改你的“阵列”解决方案,那么他很可能会引入新的错误。