1.工厂模式(Factory)

<?php
namespace DesignPattern;
class Factory
{
    static function createDatabase()
    {
        $db = new Database();
        return $db;
    }
}

2.单例模式

<?php
namespace DesignPattern;
class Database
{
    static protected $db;
    private function __construct()
    {

    }

    static function getInstance()
    {
        if(self::$db)
        {
            return self::$db;
        }else{
            self::$db = new self();
            return self::$db;
        }

    }
}

3.注册模式(Register)

<?php
namespace DesignPattern;
class Register
{
    protected static $objects;

    static function set($alias, $object)
    {
        self::$objects[$alias] = $object;
    }

    static function get($alias)
    {
        return self::$objects[$alias];
    }

    static function _unset($alias)
    {
        unset(self::$objects[$alias]);
    }
}

4.适配器模式 (Adapter)

  1. 将截然不同的函数接口封装成统一的API
  2. 示例,PHP的数据库驱动有mysql,mysqli,pdo等。cache适配器:memcached,redis,file,apc统一成一致的API
// thinkphp/library/think/cache
// thinkphp/library/think/log

5.策略模式(Strategy)

  1. 将一组特定的行为和算法封装成类,以适应某些特定的上下文环境
  2. 示例:电商网站系统,针对男性女性用户各自跳转不同的商品目录,并且所有广告位展示不同的广告
  3. 使用策略模式可以实现Ioc,依赖倒置、控制反转
// UserStrategy.php
<?php
namespace DesignPattern;

interface UserStrategy
{
    function showAd();
    function showCategory();
}

// FemaleUserStrategy.php
<?php
namespace DesignPattern;

class FemaleUserStrategy implements UserStrategy
{
    function showAd()
    {
        echo '2014新款女装';
    }

    function showCategory()
    {
        echo '女装';
    }
}

// MaleUserStrategy.php
<?php
namespace DesignPattern;
class MaleUserStrategy implements UserStrategy
{
    function showAd()
    {
        echo 'Iphone6';
    }

    function showCategory()
    {
        echo '电子产品';
    }
}

// index.php
class Page
{
    /**
     * @var DesignPattern\UserStrategy
     */
    protected $strategy;
    function index()
    {
        $this->strategy->showAd();
        echo "<br>";
        $this->strategy->showCategory();
    }

    function setStrategy(DesignPattern\UserStrategy $strategy)
    {
        $this->strategy = $strategy;
    }
}

$page = new Page();
if(isset($_GET['female']))
{
    $strategy = new DesignPattern\FemaleUserStrategy();
}else{
    $strategy = new DesignPattern\MaleUserStrategy();
}
$page->setStrategy($strategy);
$page->index();

6.数据对象映射模式

7.观察者模式(Observer)

  1. 当一个对象状态发生改变时,依赖它的对象全部会收到通知,并自动更新
  2. 场景:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件主体的代码
  3. 观察者模式实现了低耦合,非侵入式的通知和更新机制
// Observer.php
<?php
namespace DesignPattern;

interface Observer
{
    function update($event_info = null);
}

// EventGenerator.php
<?php
namespace DesignPattern;
abstract class EventGenerator
{
    private $observers = array();
    function addObserver(Observer $observer) {
        $this->observers[] = $observer;
    }

    function notify() {
        foreach ($this->observers as $observer) {
            $observer->update();
        }
    }
}

// index.php
class Event extends \DesignPattern\EventGenerator
{
    function trigger()
    {
        echo "Event<br>\n";

        $this->notify();
        //update
//        echo "逻辑1<br>\n";
//        echo "逻辑2<br>\n";
//        echo "逻辑3<br>\n";
    }
}
class Observer1 implements \DesignPattern\Observer
{
    function update($event_info = null)
    {
        echo "逻辑1<br>\n";
    }
}
class Observer2 implements \DesignPattern\Observer
{
    function update($event_info = null)
    {
        echo "逻辑2<br>\n";
    }
}
$event = new Event();
$event->addObserver(new Observer1());
$event->addObserver(new Observer2());
$event->trigger();

8.原型模式(Prototype)

  1. 与工厂模式作用类似,都是用来创建对象的
  2. 与工厂模式的实现不同,原型模式是先创建好一个原型对象,然后通过clone原型对象来创建新的对象。这样就免去了类创建时重复的初始化操作
  3. 原型模式适用于大对象的创建。创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需要内存拷贝即可
$prototype = new \DesignPattern\Canvas();
$prototype->init();

$canvas1 = clone $prototype;
$canvas1->rect(3, 6, 4, 12);
$canvas1->draw();
echo "============================<br>\n";

$canvas2 = clone $prototype;
$canvas2->rect(1, 3, 2, 6);
$canvas2->draw();

9.装饰器模式 (Decorator)

  1. 可以动态添加修改类的功能
  2. 一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重新实现类的方法
  3. 使用装饰器模式,仅需在运行时添加一个装饰器对象即可实现,可以实现最大的灵活性
// DrawDecorator.php
<?php
namespace DesignPattern;
interface DrawDecorator
{
    function beforeDraw();
    function afterDraw();
}

// ColorDecorator.php
<?php
namespace DesignPattern;
class  ColorDecorator implements DrawDecorator
{
    protected $color;
    function __construct($color = 'red')
    {
        $this->color = $color;
    }

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

// Canvas.php
<?php
namespace DesignPattern;
class Canvas
{
    public $data;
    protected  $decorators = array();
    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;
    }

    // 接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法
    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 or $k1 > $a2) continue;
            foreach ($line as $k2 => $char) {
                if($k2 < $b1 or $k2 > $b2) continue;
                $this->data[$k1][$k2] = '=';
            }
        }
    }
}

//index.php
$prototype = new \DesignPattern\Canvas();
$prototype->init();

$canvas1 = clone $prototype;
// 接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法
$canvas1->addDecorator(new \DesignPattern\ColorDecorator('green'));
$canvas1->rect(3, 6, 4, 12);
$canvas1->draw();

10.迭代器模式 (Iterator) SPL

  1. 在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素
  2. 相比于传统的编程模式,迭代器模式可以隐藏遍历元素的所需的操作

11.代理模式(Proxy)

  1. 在客户端与实体之间建立一个代理对象,客户端对实体进行操作全部委派给代理对象,隐藏实体的具体实现细节。
  2. Proxy还可以与业务代码分离,部署到另外的服务器。业务代码中通过RPC来委派任务。
Scroll to Top