最新消息:

设计模式之装饰器模式

未分类 362浏览 0评论

基本概念:

    装饰器模式(Decorator)可以动态地添加修改类的功。

应用场景:

    一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,是新增一个子类继承它,并重新实现类的方法。使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以最大化实现代码的灵活性。

本文代码是基于 《设计模式之原型模式》    一文实现。

定义装饰器接口类

interface DrawDecorator
{
    function beforeDraw();

    function afterDraw();
}

定义颜色装饰器类,并实现装饰器接口

class ColorDecorator implements DrawDecorator
{
    protected $color;
    function __construct($color = 'red')
    {
        $this->color = $color;
    }

    function beforeDraw()
    {
        // TODO: Implement beforeDraw() method.
        echo "<div style='color:$this->color'>";
    }

    function afterDraw()
    {
        // TODO: Implement afterDraw() method.
        echo "</div>";
    }
}

定义尺寸装饰器类,并实现装饰器接口

class SizeDecorator implements DrawDecorator
{
    protected $size;
    function __construct($size = 'red')
    {
        $this->size = $size;
    }

    function beforeDraw()
    {
        // TODO: Implement beforeDraw() method.
        echo "<div style='font-size:$this->size'>";
    }

    function afterDraw()
    {
        // TODO: Implement afterDraw() method.
        echo "</div>";
    }
}

接下来在canvas类中添加装饰器操作方法(这里只写两个 beforeDecorator 和 afterDecorator)

/**
 * 新建canvas类
 * Class Canvas
 * @package Wecot
 */
class Canvas implements DrawDecorator
{
    public $data;
    private $decorators;

    function init($width = 30, $height = 15)
    {
        $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()
    {
        // TODO: Implement beforeDraw() method.
        foreach ($this->decorators as $decorator){
            $decorator->beforeDraw();
        }
    }

    function afterDraw()
    {
        // TODO: Implement afterDraw() method.
        $decorators = array_reverse($this->decorators);
        foreach ($decorators as $decorator){
            $decorator->beforeDraw();
        }
    }
    function draw()
    {
        $this->beforeDraw();
        foreach ($this->data as $heightArr) {
            foreach ($heightArr as $widthChar) {
                echo $widthChar;
            }
//            echo PHP_EOL;
            echo "<br>\n";
        }
        $this->afterDraw();
    }


    function rect($a1, $a2, $b1, $b2)
    {
        foreach ($this->data as $k1 => $line) {
            if ($k1 < $a1 or $k1 > $a2) continue;
            foreach ($line as $k2 => $widthChar) {
                if ($k2 < $b1 or $k2 > $b2) continue;
                //对数组中元素置空
//                $this->data[$k1][$k2] = ' ';
                $this->data[$k1][$k2] = '&nbsp;&nbsp;';
            }
        }
    }
}

装饰器调用执行:

$canvas = new \Wecot\Canvas();
$canvas->init();
//添加颜色装饰器
$canvas->addDecorator(new \Wecot\ColorDecorator('blue'));
//添加尺寸装饰器
$canvas->addDecorator(new \Wecot\SizeDecorator(25));
$canvas->rect(3, 6,4,15);
$canvas->draw();

以上,装饰器模式完全避免了程序的高度内聚,和多次集成重写的繁杂方式。使用装饰器模式可以基本实现无侵入式的实现需求。

转载请注明:微刻 blog.wecot.cn » 设计模式之装饰器模式

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 你这个 跟 韩天峰大佬 将的设计模式 感觉一样的 从代码看
    aaa2年前 (2019-05-31)回复
    • 是的,学习韩大大,并总结。
      2年前 (2019-06-21)回复