设计模式之PHP实现(二)

- 7 mins

如未阅读第一部分,请先去阅读第一部分

观察者模式

概念

当一个对象状态发生变化时,依赖其的所有对象都会收到通知,并且自动更新。

场景

当事件发生后,需要执行一连串的更新操作。

传统的变成模式,就是在事件代码后直接加入处理逻辑,当更新的逻辑增加之后,代码就会变得非常难以维护。

观察模式实现了低耦合,非入侵式通知与更新机制。

事件触发的抽象类 事件处理与消息通知

<?php

require_once 'Loader.php';

abstract class EventGenerator {

    private $observers = array();

    function addObserver(Observer $observer) {
        $this->observers[] = $observer;
    }

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

}

事件触发的抽象类 事件处理与消息通知

<?php

require_once 'Loader.php';

abstract class EventGenerator {

    private $observers = array();

    function addObserver(Observer $observer) {
        $this->observers[] = $observer;
    }

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

观察者接口 每次继承都是生成一个可实例化的观察者

<?php

require_once "Loader.php";

interface Observer {

    function update();

}

执行

<?php

require_once 'Loader.php';

class Event extends EventGenerator {

    function triger() {
        echo "Event \n"; // Event trigger
    }

}

class Observer1 implements Observer {

    function update() {
        echo "Logic1 \n"; // Do something
    }

}

class Observer2 implements Observer {

    function update() {
        echo "Logic2 \n"; // Do something
    }

}

$event = new Event; // 事件处理类
$event->addObserver(new Observer1); // 添加第一个观察者
$event->addObserver(new Observer2); // 添加第二个观察者
$event->triger();  // 事件处理
$event->notify(); // 处理完成后给所有观察者的通知

Observer Pattern

策略模式

策略模式 是指针对不同的参数,执行不同的策略,这种对于较大体量或者代码较多的网站比较适用

针对不用的使用场景,不同的参数调用不同的策略模式,这样减少了大量的if else 操作,减少了代码混乱,增加了可读性。

规则接口

<?php

interface Strategy {

    function showAD();
    function showDetail();

}

策略一

<?php

require_once 'Loader.php';

class NormalUser implements Strategy {

    function showAD () {
        echo "There are some advertisement's";
    }

    function showDetail () {
        echo "There are some detail's";
    }
}

策略二

<?php

require_once 'Loader.php';

class VipUser implements Strategy {

    function showAD() {
        echo "This is some advertisement for VIP";
    }

    function showDetail() {
        echo "This is detail of goods which named 'strategy' for VIP";
    }

}

执行文件

<?php

require_once 'Loader.php';

class Execute {

    protected $s;

    function index() {
        echo "AD \n";
        $this->$strategy->showAD();
        echo 'Detail \n';
        $this->$strategy->showDetail();
    }

    function setStrategy(Strategy $strategy) {
        $this->$s= $strategy;  // 这里还是考虑用静态变量吧,这种变量设置方法可能会抽风
    }

}

$execute = new Execute();
$source = 1;
if ($source == 1) {
    $strategy = new NormalUser();
} else {
    $strategy = new VipUser();
}
$execute->setStrategy($strategy);
$execute->index();

适配器模式

通常是给不同权限执行不同的代码。例如:相同操作下,不同的账户/角色/权限执行不同的逻辑,产生不同的数据。

避免面向过程的开发中写过多的判断流程。

目录结构

|__ use.php
|__ Adapt
    |__ IDatabase.php
    |__ Database
        |__ MysqlDB.php
        |__ MysqliDB.php
        |__ PDODB.php

标准接口(IDatabase.php)

<?php

namespace Adapt;

interface IDatabase {

    function connect($host, $user, $passwd, $dbname);
    function query($sql);
    function close();

}

MySQL 方法连接(PHP7已弃用)(MysqlDB.php)

<?php

namespace Adapt\Database;

use Adapt\IDatabase;

class MysqlDB implements IDatabase {

    protected $conn;

    function connect($host, $user, $passwd, $dbname) {
        $conn = mysql_connect($host, $user, $passwd);
        mysql_select_db($dbname, $conn);
        $this->$conn = $conn;
    }

    function query($sql) {
        $res = mysql_query($sql, $this->$conn);
        return $res;
    }

    function close() {
        mysql_close($this->$conn);
    }

}

MySQLi 方法连接(MysqliDB.php)

<?php

namespace Adapt\Database;

use Adapt\IDatabase;

class MysqliDB implements IDatabase {

    protected $conn;

    function connect($host, $user, $passwd, $dbname) {
        $conn = mysqli_connect($host, $user, $passwd, $dbname);
        $this->conn = $conn;
    }

    function query($sql) {
        return mysqli_query($this->conn, $sql);
    }

    function close() {
        mysqli_close($this->conn);
    }

}

PDO方法(PDODB.php)

<?php

namespace Adapt\Database;

use Adapt\IDatabase;

class PDODB implements IDatabase {

    protected $conn;

    function connect ($host, $user, $passwd, $dbname) {
        $conn = new \PDO("mysql:host={$host};dbname={$dbname}", $user, $passwd);
        $this->conn = $conn;
    }

    function query($sql) {
        return $this->conn->query($sql);
    }

    function close() {
        unset($this->conn);
    }

}

执行

<?php

spl_autoload_register('loadFunc');

use Adapt\Database\PDODB;
use Adapt\Database\MysqliDB;
use Adapt\Database\MysqlDB;

$myidb = new MysqliDB();
$myidb->connect('127.0.0.1', 'root', '1234', 'MyDB');
$resi = $myidb->query("select * from users");
var_dump($resi);

$mypdo = new PDODB();
$mypdo->connect('127.0.0.1', 'root', '1234', 'MyDB');
$respdo = $mypdo->query("select * from users");
var_dump($respdo);

$mydb = new MysqlDB();
$mydb->connect('127.0.0.1', 'root', '1234', 'MyDB');
$res = $mydb->query("select * from users");
var_dump($res);

function loadFunc($class) {
  // 由于use 时用的反斜线(\),而Linux中使用的是斜线(/),故需要来回转义替换一下
    $dir = __DIR__;
    $dir = str_replace('/','\\',$dir);
    $requires = $dir . '\\' . $class . '.php';
    $requires = str_replace('\\','/',$requires); 
    require $requires;
}

Modules with UML

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora