10.装饰器模式

这里写图片描述

传统方法:

//传统方法,继承并重写
class Canvas2 extends IMooc\Canvas
{
    public function draw()
    {
        echo "<div style='color:red;'>";
        parent::draw();
        echo "</div>";
    }
}

$canvas1 = new Canvas2();
$canvas1->init();
$canvas1->rect(3,6,4,12);
$canvas1->draw();

装饰器模式:

index.php

<?php

define('BASEDIR',__DIR__);

include BASEDIR . '/IMooc/Loader.php';
spl_autoload_register('\\IMooc\\Loader::autoload');

$canvas1 = new IMooc\Canvas();
$canvas1->init();
$canvas1->addDecorator(new \IMooc\ColorDrawDecorator('blue'));
$canvas1->addDecorator(new \IMooc\SizeDrawDecorator('100px'));
$canvas1->rect(3,6,4,12);
$canvas1->draw();

DrawDecorator.php

<?php

namespace IMooc;

// 1.先声明一个装饰器的接口
interface DrawDecorator
{
    //在这个方法之前,之后加一些额外的能力
    public function beforeDraw();
    public function afterDraw();
}

Canvas.php

<?php
namespace IMooc;

//模拟一个画布
class Canvas
{
    public $data;
    protected $decorators = array();

    //Decorator
    function init($width = 20, $height = 10)
    {
        $data = array();
        for($i = 0; $i < $height; $i++)
        {
            for($j = 0; $j < $width; $j++)
            {
                $data[$i][$j] = '*';
            }
        }
        $this->data = $data;
    }

    //3. 动态的增加装饰器对象
    function addDecorator(DrawDecorator $decorator)
    {
        $this->decorators[] = $decorator;
    }

    //4.添加两个调用装饰器的方法
    function beforeDraw()
    {
        //逐个调用每个装饰器提供的方法
        foreach($this->decorators as $decorator)
        {
            $decorator->beforeDraw();
        }
    }
    //5.添加两个调用装饰器的方法
    function afterDraw()
    {
        //装饰器反转,before 是先进先出,after 是后进先出
        $decorators = array_reverse($this->decorators);
        foreach($decorators as $decorator)
        {
            $decorator->afterDraw();
        }
    }

    function draw()
    {
        // 2. 在渲染画布之前,装饰器方法调用
        $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 or $k1 > $a2) continue;
            foreach($line as $k2 => $char)
            {
                if ($k2 < $b1 or $k2 > $b2) continue;
                $this->data[$k1][$k2] = '&nbsp;';
            }
        }
    }
}

ColorDrawDecorator.php

<?php

namespace IMooc;

//6.实现装饰器对象,颜色装饰器,用来修改画布的颜色,必须实现装饰器接口

class ColorDrawDecorator implements DrawDecorator
{
    protected $color;

    public function __construct($color)
    {
        $this->color = $color;
    }

    public function beforeDraw()
    {
        echo "<div style='color:{$this->color};'";
    }

    public function afterDraw()
    {
        echo "</div>";
    }
}

SizeDrawDecorator.php

<?php

namespace IMooc;

//7. 这个装饰器的作用是修改文字的大小
class SizeDrawDecorator implements DrawDecorator
{
    protected $size;

    public function __construct($size = '14px')
    {
        $this->size = $size;
    }

    public function beforeDraw()
    {
        echo "<div style='font-size:{$this->size};'";
    }

    public function afterDraw()
    {
        echo "</div>";
    }
}

<?php

interface Component
{
    public function operation();
}

class ConcreteComponent implements  Component
{
    public function operation()
    {
        echo 'do operation <br/>';
    }
}

abstract class Decorator implements Component
{
    protected $component;

    public function __construct(Component $component)
    {
        $this->component = $component;
    }

    public function operation()
    {
        $this->component->operation();
    }
}

class ConcreteDecoratorA extends Decorator
{
    public function __construct(Component $component)
    {
        parent::__construct($component);
    }

    public function operation()
    {
        parent::operation();
        echo 'do Operation AAA<br/>';
    }
}

class ConcreteDecoratorB extends Decorator
{
    public function __construct(Component $component)
    {
        parent::__construct($component);
    }

    public function operation()
    {
        parent::operation();
        echo 'do Operation BBB<br/>';
    }
}

class Client
{
    public static function main()
    {
        $decoratorA = new ConcreteDecoratorA(new ConcreteComponent());
        $decoratorA->operation();
        echo '<hr/>';
        $decoratorB = new ConcreteDecoratorB($decoratorA);
        $decoratorB->operation();
    }
}

Client::main();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值