PHP设计模式之组合模式

这里的“组合”和我们理解的组合关系不是一个意思,这里讲的“组合模式”,主要是用来处理树形结构数据。该模式只能用于树形结构的数据,所以日常中用到的并不会太多,但一旦满足了树形结构,该模式就能很好的发挥它的作用,能大大的减少代码量、写出非常简洁的代码。

Table of Contents

定义

组合模式是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。

场景

文件目录树就是一个典型的树形结构的数据。

class File
{
   private $path = '';
   private $nodes = [];
   private $fileSize = 0;

   public function __construct(string $path, int $fileSize)
  {
       $this->path = $path;
       $this->fileSize = $fileSize;
  }

   public function addNode (File $node)
  {
       $this->nodes[] = $node;
  }

   public function fileSize ()
  {
       $size = 0;

       foreach ($this->nodes as $node) {
           $size += $node->fileSize();
      }

       return $size;
  }
}

下面模拟出以下的目录树

/app

/app/1.txt
/app/a
/app/b

/app/a/a1.txt
/app/b/b1.txt
/app/b/b2.txt

测试代码如下:

$node0 = new File('/app', 0);

$node1 = new File('/app/1.txt', 1000);
$node2 = new File('/app/a', 0);
$node3 = new File('/app/b', 0);

$node21 = new File('/app/a1.txt', 1000);
$node31 = new File('/app/b1.txt', 1000);
$node32 = new File('/app/b2.txt', 1000);

$node2->addNode($node21);
$node3->addNode($node31);
$node3->addNode($node32);
$node0->addNode($node1);
$node0->addNode($node2);
$node0->addNode($node3);

// 计算目录/app/b大小
echo $node3->fileSize() . 'B' . PHP_EOL; // 2000
// 计算/app目录大小
echo $node0->fileSize() . 'B' . PHP_EOL; // 4000

总结

组合模式,将一组对象组织成树形结构,将单个对象和组合对象都看做树中的节点,以统一处理逻辑,并且它利用树形结构的特点,递归地处理每个子树,依次简化代码实现。使用组合模式的前提在于,你的业务场景必须能够表示成树形结构。所以,组合模式的应用场景也比较局限,它并不是一种很常用的设计模式。