课程名称:大话PHP设计模式
课程章节: 11-1PHP装饰器模式
课程链接
主讲老师:Rango
课程内容
给出了装饰器模式的定义,然后通过代码演示让我们更加深入了解到装饰器模式的实现原理。
课程收获
定义
1、装饰器模式(Decorator)又叫装饰者模式。
2、在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
优点
一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法。
使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵动性
应用场景
1、需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
2、需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
3、当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
代码实现
interface DrawDecorator
{
function beforeDraw();
function afterDraw();
}
class ColorDrawDecorator implements DrawDecorator
{
protected $color;
function __construct($color = 'red')
{
$this->color = $color;
}
function beforeDraw()
{
echo "<div style='color:{$this->color};'>";
}
function afterDraw()
{
echo "</div>";
}
}
class SizeDrawDecorator implements DrawDecorator
{
protected $size;
function __construct($size = '14px')
{
$this->size = $size;
}
function beforeDraw()
{
echo "<div style='font-size:{$this->size};'>";
}
function afterDraw()
{
echo "</div>";
}
}
class Canvas
{
public $data;
protected $decorators = [];
function init($width = 20, $height = 10)
{
$data = [];
for ($i = 0; $i < $height; $i++) {
for ($j = 0; $j < $width; $j++) {
$data[$i][$j] = '*';
}
}
$this->data = $data;
}
function addDecorator(DrawDecorator $decorator)
{
$this->decorators[] = $decorator;
}
function beforeDraw()
{
foreach ($this->decorators as $decorator) {
$decorator->beforeDraw();
}
}
function afterDraw()
{
$decorators = array_reverse($this->decorators);
foreach ($decorators as $decorator) {
$decorator->afterDraw();
}
}
function draw()
{
$this->beforeDraw();
foreach ($this->data as $line) {
foreach ($line as $char) {
echo $char;
}
echo "<br />\n";
}
$this->afterDraw();
}
function rect($a1, $a2, $b1, $b2)
{
foreach ($this->data as $k1 => $line) {
if ($k1 < $a1 || $k1 > $a2)
continue;
foreach ($line as $k2 => $char) {
if ($k2 < $b1 || $k2 > $b2)
continue;
$this->data[$k1][$k2] = ' ';
}
}
}
}
$canvas1 = new Canvas;
$canvas1->init();
$canvas1->addDecorator(new ColorDrawDecorator('green'));
$canvas1->addDecorator(new SizeDrawDecorator('50px'));
$canvas1->rect(3, 6, 4, 12);
$canvas1->draw();