Decorator code examples of PHP design patterns (14)

purpose

Dynamically add functionality to instances of the class

example

  • Zend Framework: Decorator of Zend_Form_Element instances

  • Web Service layer: JSON and XML decorators for REST services (Of course, only one of them can be used here)

UML graphics

★Official PHP advanced learning exchange community "click" management to organize some materials, BAT and other first-line companies have advanced knowledge systems (relevant learning materials and written interview questions) and are not limited to: distributed architecture, high scalability, high Performance, high concurrency, server performance tuning, TP6, laravel, YII2, Redis, Swoole, Swoft, Kafka, Mysql optimization, shell scripts, Docker, microservices, Nginx and other knowledge points, advanced advanced dry goods

Code

  • 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());
    }
}

test

  • 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());
    }
}

The Growth Path of PHP Internet Architect * The Ultimate Guide to "Design Patterns"

PHP Internet Architect 50K Growth Guide + Industry Problem Solving Guide (Continuous Update)

Interview with 10 companies, get 9 offers, PHP interview questions in 2020

★If you like my article and want to communicate and learn with more senior developers, get more technical consultation and guidance related to interviews with big factories, welcome to join our group, password: phpzh (Junyang number 856460874).

The latest PHP advanced tutorial in 2020, full series!

If the content is good, I hope everyone will support and encourage you to give a like/like, and welcome to communicate together; in addition, if you have any questions, you can suggest what you want to see in the comments.

Guess you like

Origin blog.csdn.net/weixin_43814458/article/details/108609392