php 设计模式(七)装饰器模式 | Leezhiy Blog

php 设计模式(七)装饰器模式

什么是装饰器模式

定义:允许向一个现有对象添加新的功能,同时又不改变其结构,这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

简单来说就是可以动态的添加修改类的功能

为什么要使用装饰器模式

如果一个类提供了一项功能,现在需要修改或者添加额外的功能,传统的编程模式是需要写个子类集成它,并重新实现类的方法。使用装饰模式仅需在运行时添加一个装饰器对象即可实现。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能中

装饰器模式的优点

(1).我们可以保证类的层次不会因过多而发生混乱。

(2).当我们需求的修改很小时,不用改变原有的数据结构。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

<?php

/**
* 创建渲染接口。
* 这里的装饰方法 renderData() 返回的是字符串格式数据。
*/
interface RenderableInterface
{
public function renderData(): string;
}

/**
* 创建 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;
}
}

/**
* 装饰者必须实现渲染接口类 RenderableInterface 契约,这是该设计
* 模式的关键点。否则,这将不是一个装饰者而只是一个自欺欺人的包
* 装。
*
* 创建抽象类 RendererDecorator (渲染器装饰者)实现渲染接口。
*/
abstract class RendererDecorator implements RenderableInterface
{
/**
* @var RenderableInterface
* 定义渲染接口变量。
*/
protected $wrapped;

/**
* @param RenderableInterface $renderer
* 传入渲染接口类对象 $renderer。
*/
public function __construct(RenderableInterface $renderer)
{
$this->wrapped = $renderer;
}
}

/**
* 创建 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();
}
}

/**
* 创建 Json 修饰者并继承抽象类 RendererDecorator 。
*/
class JsonRenderer extends RendererDecorator
{
/**
* 对传入的渲染接口对象进行处理,生成 JSON 数据。
*/
public function renderData(): string
{
return json_encode($this->wrapped->renderData());
}
}

// 测试
$webServiceObject = new Webservice('foobar');
// 用 Json 装饰器装饰 webServiceObject
$service = new JsonRenderer($webServiceObject);
// 输出结果为 json_encode('foobar');后的结果
echo $service->renderData();

// 用 xml 装饰器装饰 webServiceObject;
$service = new XmlRenderer($webServiceObject);
// 输出结果为 xml 处理后的结果
echo $service->renderData();
Buy me a cup of milkshake 🍨.
------------- 💖 🌞 本 文 结 束 😚 感 谢 您 的 阅 读 🌞 💖 -------------

欢迎关注我的其它发布渠道