设计模式之组合模式 Composite

组合模式的目的是为了将对象组合成一个树形结构以表现部分/整体的层次结构。实现组合模式能够统一地处理单个组件与整个组合体。

使用

例如表单组件中可以插入多个子组件:输入框文本框,同时在表单组件中的任何位置右可以插入其他的表单组件,这样多个子组件就能够以组合模式构成一个大的树形表单组件

代码实现

子组件都必须实现同样的接口,这里是都必须有render()方法,以为不同的表单组件渲染出不同的html格式

interface RenderableInterface
{
    public function render();
}

Form 组件能够在其中添加子组件

class Form implements RenderableInterface
{
    private $elements;

    public function render()
    {
        $formCode = '<form>';

        foreach ($this->elements as $element) {
            $formCode .= $element->render();
        }

        $formCode .= '</form>';

        return $formCode;
    }

    public function addElement(RenderableInterface $element)
    {
        $this->elements[] = $element;
    }
}

Input 与 Text 子组件则是最小的子组件,不能向其中添加功能

class InputElement implements RenderableInterface
{
    public function render() : string
    {
        return '<input type="text" />';
    }
}
class TextElement implements RenderableInterface
{
    private $text;

    public function __construct(string $text)
    {
        $this->text = $text;
    }

    public function render() : string
    {
        return $this->text;
    }
}

测试

//新建树结构的根节点
$form = new Form();
//向form节点中插入子组件
$form->addElement(new TextElement('Email:'));
$form->addElement(new InputElement());
$embed = new Form();
$embed->addElement(new TextElement('Password:'));
$embed->addElement(new InputElement());
$form->addElement($embed);

echo $form->render();

输出:

<form>Email:<input type="text" /><form>Password:<input type="text" /></form></form>