PHP模式设计之 装饰器模式

by kingzcheung on August 5, 2017

装饰器模式可以从外部对某个对象动态的添加功能而不会影响原来的对象,也不需要修改原来的类.比如原来已经有一个类实现了文本输出,现在有一个新的需求,就是为文本输出添加html标签.

先定义一个接口,render()方法只返回文本字符串:

interface HtmlInterface {
    public function render(): string;
}

实现接口:

class Html implements HtmlInterface {

    protected $data;

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

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

如果我们希望Html类返回的文本加上html 标签,就可以使用装饰器模式.

添加ElementDecorator抽象类,抽象类需要实现HtmlInterface接口(不实现此接口的话并不算装饰器):

/**
 * 添加抽象类
 * Class ElementDecorator
 */
abstract class ElementDecorator implements HtmlInterface {
    protected $wrapped;

    function __construct(HtmlInterface $html) {
        $this->wrapped = $html;
    }

}

子类只要继承上面的抽象类即可.

/**
 * 实现 DIV 标签
 * Class DivElement
 */
class DivElement extends ElementDecorator {
    public function render(): string {
        return sprintf("<div>%s</div>", $this->wrapped->render());
    }
}

/**
 * 实现 SPAN 标签
 * Class SpanElement
 */
class SpanElement extends ElementDecorator {
    public function render(): string {
        return sprintf("<span>%s</span>", $this->wrapped->render());
    }
}

最后的调用:

$html = new Html('我是一个文本');
print_r($html->render());

echo PHP_EOL;

$div = new DivElement($html);
$span = new SpanElement($html);
print_r($div->render());
echo PHP_EOL;
print_r($span->render());