php的结构型设计模式,PHP 设计模式 - 结构型 - 装饰模式(Decorator)

1. 模式定义

装饰器模式能够从一个对象的外部动态地给对象添加功能。

一般给一个对象加功能有如下三种方式:

直接修改这个对象 => 这是不可取的,会影响其他调用这个对象的类或对象

派生对于的子类来拓展 => 随着扩展越多,子类会越膨胀

对象组合 √

装饰器模式就是采用动态组合的方式,实现给一个对象加功能。

最常见的示例是 Web服务层——为REST 服务提供json 和xml装饰器

2. UML类图

d72976f48a75

image.png

3. 示例代码

RenderInterface.php

namespace DesignPattern\Structural\Decorator;

/**

* 渲染器接口

* Class RendererInterface

* @package DesignPattern\Structural\Decorator

*/

interface RendererInterface

{

//渲染数据

public function renderData();

}

WebService.php

namespace DesignPattern\Structural\Decorator;

class WebService implements RendererInterface

{

protected $data;

public function __construct($data)

{

$this->data = $data;

}

public function renderData()

{

return $this->data;

}

}

Decorator.php

namespace DesignPattern\Structural\Decorator;

/**

* 装饰器: 必须实现 RendererInterface 接口, 这是装饰器模式的主要特点,

* 否则的话就不是装饰器而只是个包裹类

* Class Decorator

* @package DesignPattern\Structural\Decorator

*/

abstract class Decorator implements RendererInterface

{

/** @var $renderer RendererInterface */

protected $renderer;

public function __construct(RendererInterface $renderer)

{

$this->renderer = $renderer;

}

}

RenderXml .php

namespace DesignPattern\Structural\Decorator;

/**

* 渲染成XML

* Class RenderXml

* @package DesignPattern\Structural\Decorator

*/

class RenderXml extends Decorator

{

public function renderData()

{

$data = $this->renderer->renderData();

$doc = new \DOMDocument();

foreach ($data as $key => $val) {

$doc->appendChild($doc->createElement($key, $val));

}

return $doc->saveXML();

}

}

RenderJson.php

namespace DesignPattern\Structural\Decorator;

/**

* 渲染成 Json

* Class RenderXml

* @package DesignPattern\Structural\Decorator

*/

class RenderJson extends Decorator

{

public function renderData()

{

$output = $this->renderer->renderData();

return json_encode($output);

}

}

DecoratorTest

namespace DesignPattern\Tests;

use DesignPattern\Structural\Decorator\RenderJson;

use DesignPattern\Structural\Decorator\RenderXml;

use DesignPattern\Structural\Decorator\WebService;

use PHPUnit\Framework\TestCase;

class DecoratorTest extends TestCase

{

protected $service;

protected function setUp(): void

{

$this->service = new WebService(array('foo' => 'bar'));

}

public function testJsonDecorator()

{

// Wrap service with a JSON decorator for renderers

$service = new RenderJson($this->service);

// Our Renderer will now output JSON instead of an array

$this->assertEquals('{"foo":"bar"}', $service->renderData());

}

public function testXmlDecorator()

{

// Wrap service with a XML decorator for renderers

$service = new RenderXml($this->service);

// Our Renderer will now output XML instead of an array

$xml = '<?xml version="1.0"?>bar';

$this->assertXmlStringEqualsXmlString($xml, $service->renderData());

}

/**

* The first key-point of this pattern :

*/

public function testDecoratorMustImplementsRenderer()

{

$className = 'DesignPattern\Structural\Decorator\Decorator';

$interfaceName = 'DesignPattern\Structural\Decorator\RendererInterface';

$this->assertTrue(is_subclass_of($className, $interfaceName));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值