目的
动态地为类的实例添加功能
例子
-
Zend Framework: Zend_Form_Element 实例的装饰者
-
Web Service层:REST服务的JSON与XML装饰器(当然,在此只能使用其中的一种)
UML图
代码
- RenderableInterface.php
<?php
namespace DesignPatterns\Structural\Decorator;
/**
* 创建渲染接口。
* 这里的装饰方法 renderData() 返回的是字符串格式数据。
*/
interface RenderableInterface
{
public function renderData(): string;
}
- Webservice.php
<?php
namespace DesignPatterns\Structural\Decorator;
/**
* 创建 Webservice 服务类实现 RenderableInterface。
* 该类将在后面为装饰者实现数据的输入。
*/
class Webservice implements RenderableInterface
{
/**
* @var string
*/
private $data;
/**
* 传入字符串格式数据。
*/
public function __construct(string $data)
{
$this->data = $data;
}
/**
* 实现 RenderableInterface 渲染接口中的 renderData() 方法。
* 返回传入的数据。
*/
public function renderData(): string
{
return $this->data;
}
}
- RendererDecorator.php
<?php
namespace DesignPatterns\Structural\Decorator;
/**
* 装饰者必须实现渲染接口类 RenderableInterface 契约,这是该设计
* 模式的关键点。否则,这将不是一个装饰者而只是一个自欺欺人的包
* 装。
*
* 创建抽象类 RendererDecorator (渲染器装饰者)实现渲染接口。
*/
abstract class RendererDecorator implements RenderableInterface
{
/**
* @var RenderableInterface
* 定义渲染接口变量。
*/
protected $wrapped;
/**
* @param RenderableInterface $renderer
* 传入渲染接口类对象 $renderer。
*/
public function __construct(RenderableInterface $renderer)
{
$this->wrapped = $renderer;
}
}
- XmlRenderer.php
<?php
namespace DesignPatterns\Structural\Decorator;
/**
* 创建 Xml 修饰者并继承抽象类 RendererDecorator 。
*/
class XmlRenderer extends RendererDecorator
{
/**
* 对传入的渲染接口对象进行处理,生成 DOM 数据文件。
*/
public function renderData(): string
{
$doc = new \DOMDocument();
$data = $this->wrapped->renderData();
$doc->appendChild($doc->createElement('content', $data));
return $doc->saveXML();
}
}
- JsonRenderer.php
<?php
namespace DesignPatterns\Structural\Decorator;
/**
* 创建 Json 修饰者并继承抽象类 RendererDecorator 。
*/
class JsonRenderer extends RendererDecorator
{
/**
* 对传入的渲染接口对象进行处理,生成 JSON 数据。
*/
public function renderData(): string
{
return json_encode($this->wrapped->renderData());
}
}
测试
- Tests/DecoratorTest.php
<?php
namespace DesignPatterns\Structural\Decorator\Tests;
use DesignPatterns\Structural\Decorator;
use PHPUnit\Framework\TestCase;
/**
* 创建自动化测试单元 DecoratorTest 。
*/
class DecoratorTest extends TestCase
{
/**
* @var Decorator\Webservice
*/
private $service;
/**
* 传入字符串 'foobar' 。
*/
protected function setUp()
{
$this->service = new Decorator\Webservice('foobar');
}
/**
* 测试 JSON 装饰者。
* 这里的 assertEquals 是为了判断返回的结果是否符合预期。
*/
public function testJsonDecorator()
{
$service = new Decorator\JsonRenderer($this->service);
$this->assertEquals('"foobar"', $service->renderData());
}
/**
* 测试 Xml 装饰者。
*/
public function testXmlDecorator()
{
$service = new Decorator\XmlRenderer($this->service);
$this->assertXmlStringEqualsXmlString('<?xml version="1.0"?><content>foobar</content>', $service->renderData());
}
}
PHP 互联网架构师 50K 成长指南+行业问题解决总纲(持续更新)
面试10家公司,收获9个offer,2020年PHP 面试问题
★如果喜欢我的文章,想与更多资深开发者一起交流学习的话,获取更多大厂面试相关技术咨询和指导,欢迎加入我们的群啊,暗号:phpzh(君羊号码856460874)。
内容不错的话希望大家支持鼓励下点个赞/喜欢,欢迎一起来交流;另外如果有什么问题 建议 想看的内容可以在评论提出
网友评论