装饰器模式
如果想要为某个类(类A)修改或添加新的功能的时候,传统的做法无非就是在原有的类(类A)中进行修改,或者创建一个子类(类B)来继承这个类进行重写等操作。显然,直接修改类A的方法是不可取的,使用继承的方式虽然不会去修改类A,但会使类的层次增多。这时可以使用装饰器模式
装饰器模式又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。废话不多说,直接上代码
代码讲解
下面这段代码 Service 是最初的类,想要进行修改的是该类中的 renderData 方法 ,使用了装饰器模式创建出了 XmlService 和 JsonService 对 renderData 方法进行重写。
/**
* 这里是一个渲染接口,返回字符串数据
*/
interface RendererInterface
{
public function renderData(): string ;
}
/**
* 创建了一个Service服务类 去实现了上面的渲染接口
*/
class Service implements RendererInterface
{
protected $data;
public function __construct(string $data)
{
$this->data=$data;
}
/**
* 实现了RendererInterface接口中的方法
* @return string
*/
public function renderData(): string
{
return $this->data;
}
}
/**
* 装饰者必须实现渲染接口类 RenderableInterface 契约,这是该设计
* 模式的关键点。否则,这将不是一个装饰者而只是一个自欺欺人的包
* 装。
*
* 创建抽象类 RendererDecorator (渲染器装饰者)实现渲染接口。
*/
abstract class RendererDecorator implements RendererInterface
{
protected $wrapped;
/**
* 传入渲染接口类对象
* Decorator constructor.
* @param RendererInterface $renderer
*/
public function __construct(RendererInterface $renderer)
{
$this->wrapped = $renderer;
}
}
/**
* 创建 Xml 修饰者并继承抽象类 RendererDecorator 。
*/
class XmlService extends RendererDecorator
{
/**
* 对传入的渲染接口对象进行处理,生成 xml 数据。
*/
public function renderData(): string
{
$data = $this->wrapped->renderData();
return '生成xml类型的数据'.$data;
}
}
class JsonService extends RendererDecorator
{
/**
* 对传入的渲染接口对象进行处理,生成 JSON 数据。
*/
public function renderData(): string
{
$data = $this->wrapped->renderData();
return '生成json类型的数据'.$data;
}
}
$service=new Service('foobar');
echo $service->renderData().PHP_EOL;
$xml=new XmlService($service);
echo $xml->renderData().PHP_EOL;
$json=new JsonService($service);
echo $json->renderData().PHP_EOL;