组合模式用来解决整体和部分可以一致对待的问题;
比如说 文件夹 和其下的 文件;
可以复制文件也可以复制整个文件夹;
组合模式是将对象组合成树形结构以表示整体和部分的层次结构;
可以方便的增加节点;
组合模式分为两种;
我们先来说透明组合模式;
Component:包含树枝节点和叶子节点方法的抽象类
Composite:树枝节点 有子节点  示例中指 Dir 文件夹
Leaf:叶子节点 没有子节点 示例中指 File 文件
包含树枝节点和叶子节点方法的抽象类
Component.php
<?php
namespace Baijunyao\DesignPatterns\SafeComposite;
/**
 * 包含树枝节点和叶子节点方法的抽象类
 *
 * Class Component
 * @package Baijunyao\DesignPatterns\SafeComposite
 */
abstract class Component
{
    /**
     * @var
     */
    protected $name;
    /**
     * Component constructor.
     * @param $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }
    /**
     * @return mixed
     */
    abstract public function display();
}文件夹
Dir.php
<?php
namespace Baijunyao\DesignPatterns\SafeComposite;
/**
 * 文件夹
 *
 * Class Dir
 * @package Baijunyao\DesignPatterns\SafeComposite
 */
class Dir extends Component
{
    /**
     * @var array
     */
    protected $children = [];
    /**
     * 添加子节点
     *
     * @param Component $component
     */
    public function add(Component $component)
    {
        $this->children[] = $component;
    }
    /**
     * @return mixed|string
     */
    public function display()
    {
        $nameStr = $this->name .'<br>';
        foreach ($this->children as $k => $v) {
            $nameStr .= '--' . $v->display();
        }
        return $nameStr;
    }
}文件
File.php
<?php
namespace Baijunyao\DesignPatterns\SafeComposite;
/**
 * 文件
 *
 * Class File
 * @package Baijunyao\DesignPatterns\SafeComposite
 */
class File extends Component
{
    /**
     * @param Component $component
     * @throws \Exception
     */
    public function add(Component $component)
    {
        throw new \Exception('文件不能添加子节点');
    }
    /**
     * @return mixed|string
     */
    public function display()
    {
        return '--' . $this->name .'<br>';
    }
}运行;
index.php
<?php
namespace Baijunyao\DesignPatterns\SafeComposite;
require __DIR__.'/../vendor/autoload.php';
/**
 * 客户端
 *
 * Class Client
 * @package Baijunyao\DesignPatterns\SafeComposite
 */
class Client
{
    /**
     * 运行
     */
    public function run()
    {
        $designPatterns = new Dir('design-patterns');
        $classAdapter = new Dir('ClassAdapter');
        $objectAdapter = new Dir('ObjectAdapter');
        $safeComposite = new Dir('SafeComposite');
        $designPatterns->add($classAdapter);
        $designPatterns->add($objectAdapter);
        $designPatterns->add($safeComposite);
        $componentFile = new File('Component.php');
        $dirFile = new File('Dir.php');
        $fileFile = new File('File.php');
        $indexFile = new File('index.php');
        $safeComposite->add($componentFile);
        $safeComposite->add($dirFile);
        $safeComposite->add($fileFile);
        $safeComposite->add($indexFile);
        echo $designPatterns->display();
    }
}
$client = new Client();
$client->run();运行结果是这个样子的;
我们看一眼 UML ;
再回头看下 File.php ;
File 作为叶子其下是不能再有子节点的;
但是为了让树枝节点和叶子能有一个统一的操作;
我们在抽象类 Component.php 中定义了 add 方法;
作为示例为了简化只写了个 add 配套的 remove 等都没写;
这种方式是透明了却不安全;
我们又不得不在 File 的 add 方法中抛出错误;
github示例:https://github.com/baijunyao/design-patterns/tree/master/TransparentComposite
本文为白俊遥原创文章,转载无需和我联系,但请注明来自白俊遥博客https://baijunyao.com 欢迎捐赠赞赏加入组织创建QQ群及捐赠渠道
                zhaoqinghuan :这个示例代码放错了,这篇文章说的是Transparent Composite(透明组合模式)但是示例代码中却给的是安全组合模式的代码(Safe Composite)!
2019-01-05 11:14:44 回复
最新评论