分类 设计模式 下的文章

设计模式之享元模式

<?php
// 享元模式: 简单来说就是减少程序运行中产生的细粒度对象
// 比如权限控制中的权限对象的产生, 可以将不变且重复出现的数据分离出来共享, 即 "入口"=>"权限",如果在内存中有,则返回这个唯一标识码("入口"=>"权限")所标识的对象


class AuthFlyWeightFactory
{
    protected static $ins;
    protected $authList = [];

    protected function __construct(){
        $this->authList = array();
    }

    public function getIns()
    {
        if (!self::$ins instanceof self) {
            self::$ins = new self();
        }
        return self::$ins;
    }

    public function getAuthFlyWeight($authCondition)
    {
        if ( !isset($this->authList[$authCondition]) ) {
            $this->authList[$authCondition] = new AuthFlyWeight($authCondition);
        }

        return $this->authList[$authCondition];
    }
}

class AuthFlyWeight
{
    public function __construct($authCondition)
    {
        list($this->entry,$this->permit) = explode(',',$authCondition);
    }

    public function match($entry,$permit)
    {
        return $this->entry == $entry && $this->permit == $permit;
    }
}

class SecurityMgr 
{
    protected $userData;
    protected static $ins;
    protected $userAuth;

    public function getIns()
    {
        if (!self::$ins instanceof self) {
            self::$ins = new self();
        }
        return self::$ins;
    }    

    protected function __construct()
    {
        // 从数据库获取所有用户权限信息
        $this->userData = array(
            ['tom','username','update'],
            ['jay','nickname','del'],
            ['tom','username','update'],
        );
    }

    public function login($username)
    {
        if ( !isset($this->userAuth[$username]) ) {
            $this->userAuth[$username] = $this->queryUser($username);
        }
    }

    public function queryUser($username)
    {
        $col = array();
        foreach ($this->userData as $user) {
            if ($username == $user[0]) {
                $col[] = AuthFlyWeightFactory::getIns()->getAuthFlyWeight($user[1] . ',' . $user[2]);
            }
        }
        return $col;
    }

    public function hasPermit($username,$entry,$permit)
    {
        if ( empty($this->userAuth[$username]) ) {
            return false;
        }

        foreach ($this->userAuth[$username] as $authFlyWeight) {
            if ($authFlyWeight->match($entry,$permit)) {
                return true;
            }
        }

        return false;
    }
}

$mgr = SecurityMgr::getIns();
$mgr->login("tom");
$mgr->login("jay");
var_dump($mgr->hasPermit("tom", "username", "update"));
var_dump($mgr->hasPermit("jay", "nickname", "del"));

设计模式之外观模式

<?php

// 外观模式 实现文件加密
// 三个子系统, 分别是文件读取 ; 文件加密 ; 文件保存

class FileEncException extends Exception{}

class FileRead
{
    public function read($fileSrc)
    {
        if (!is_file($fileSrc)) {
            throw new FileEncException('file not exists');
        }
        $raw = file_get_contents($fileSrc);
        return $raw;
    }
}

class CipherMachine
{
    public function encrypt($raw)
    {
        $rawArr = explode('',$raw);
        $encStr = '';
        foreach ($rawArr as $li) {
            $tmp = chr(ord($li) % 7);
            $encStr .= $tmp;
        }
        return $encStr;
    }
}

class FileWriter
{
    public function write($string,$fileDes)
    {
        return file_put_contents($fileDes,$string);
    }
}

// 外观类
class EncryptFacade
{
    public function __construct()
    {
        $this->FileRead = new FileRead();
        $this->CipherMachine = new CipherMachine();
        $this->FileWriter = new FileWriter();
    }

    public function encFile($fileSrc,$fileDes)
    {
        try {

            $raw = $this->FileRead->read($fileSrc);
            $encStr = $this->CipherMachine->encrypt($raw);   
            $this->FileWriter->write($encStr,$fileDes);

        } catch (FileEncException $e) {
            return false;
        }

        return true;
    }
}

// 客户端调用
$EncryptFacade = new EncryptFacade();
$EncryptFacade->encFile('a.txt','b.txt');

设计模式之组合模式

<?php
// 组合模式 (当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了)

// 例子 部门 -> 部门(Composite) | 员工(Leaf)
abstract class Component 
{
    public function add(Component $com) 
    {
        throw new Exception(__METHOD__ . ' not implemented');
    }

    public function remove(Component $com)
    {
        throw new Exception(__METHOD__ . ' not implemented');
    }

    abstract public function getName();

    public function getChild()
    {
        throw new Exception(__METHOD__ . ' not implemented');
    }
}

class DepComposite extends Component
{   
    protected $child = array();

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

    public function add(Component $com)
    {
        $this->child[] = $com->getName();
    }

    public function remove(Component $com)
    {
        if (in_array($com->getName(),$this->child)) {
            unset($this->child[$com->getName()]);
        }
    }

    public function getChild()
    {
        return $this->child;
    }

    public function getName()
    {
        return $this->name;
    }
}

class Employee extends Component
{
    protected $child = array();

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

    public function getName()
    {
        return $this->name;
    }
}

$headOffice = new DepComposite('head_office');
$brandOffice1 = new DepComposite('brand_office1');
$brandOffice1->add(new Employee('jay'));
$brandOffice1->add(new Employee('chou'));
print_r($brandOffice1->getChild());
// 组合对象和简单对象都有 'getChild'方法, 忽略对象组合和个别对象之间的差别
$brandOffice2 = new DepComposite('brand_office2');
$headOffice->add($brandOffice1);
$headOffice->add($brandOffice2);
print_r($headOffice->getChild());

设计模式之命令模式

<?php
// 例子 : 播放器
// 命令模式 对象:命令(开始,暂停),接受者(播放器),执行者(invoker)

interface Command
{   
    public function __construct(Receiver $receiver);
    public function exec();
}

interface Receiver
{
    public function getStatus();
}

class Telecontroller implements Receiver
{
    protected $statusArr = array(
        'play',
        'stop'
    );

    public function __construct()
    {
        $this->status = 'stop';
    }

    public function setPlay()
    {
        $this->status = 'play';
    }

    public function setStop()
    {
        $this->status = 'stop';
    }

    public function getStatus()
    {
        return $this->status;
    }
}

class PlayCommand implements Command
{
    public function __construct(Receiver $receiver)
    {
        $this->receiver = $receiver;
    }

    public function exec()
    {
        $this->receiver->setPlay();
    }
}


class StopCommand implements Command
{
    public function __construct(Receiver $receiver)
    {
        $this->receiver = $receiver;
    }

    public function exec()
    {
        $this->receiver->setStop();
    }
}

class invoker 
{
    public $logQueue = array();

    public function setCommand(Command $command)
    {
        $this->command = $command;
    }

    protected function log($commandName)
    {
        $this->logQueue[] = $commandName;
    }

    public function action()
    {
        // 比如action之前记录日志
        $this->log(get_class($this->command));
        $this->command->exec();
    }
}


$telecontroller = new Telecontroller(); // 接受者(遥控器), 可以是其他对象, 电视机, 洗衣机等等....

echo $telecontroller->getStatus() . PHP_EOL;
$palyCommand = new PlayCommand($telecontroller);
$stopCommand = new StopCommand($telecontroller);

$invoker = new invoker(); 
// 为什么不直接是command直接调用receiver的方法呢? 
// 其实是为了最大限度降低耦合, 客户端不必关心命令会被怎样的"姿势"调用, 统一交给invoker处理
// 命令只需注意两个问题: 接受者是谁, 让接受者做什么;
// 至于接受者什么时候执行, 执行命令前会不会做些"预备工作", 或者执行完之后会不会有什么"清理工作".... , 都不是客户端所关心的问题
$invoker->setCommand($palyCommand);
$invoker->action();
echo $telecontroller->getStatus() . PHP_EOL;
$invoker->setCommand($stopCommand);
$invoker->action();
echo $telecontroller->getStatus() . PHP_EOL;

// 执行过的命令
print_r($invoker->logQueue);

// 感觉命令模式跟桥接模式相似的地方挺多的...

设计模式之职责链

<?php
// 职责链模式 - 实现过滤器

interface Filter
{
    public function handle($resource);
}

class FilterChain implements Filter
{
    public function addFilter(Filter $filter)
    {
        $this->filter[] = $filter;
        return $this;
    }

    public function handle($resource)
    {
        foreach ($this->filter as $filter) {
            $resource = $filter->handle($resource);
        }
        return $resource;
    }
}

class HtmlFilter implements Filter
{
    public function handle($resource)
    {
        return strip_tags($resource);
    }
}

class DbFileter implements Filter
{
    public function handle($resource)
    {
        return mysql_real_escape_string($resource);
    }
}

class ResourceProcessor
{
    protected $FilterManage = null;

    public function __construct($resource,Filter $filterChain)
    {
        $this->resource = $resource;
        $this->filterChain = $filterChain;
    }

    public function process()
    {
        return $this->filterChain->handle($this->resource);
    }
}

$msg = <<<EOT
    <html></html>
    '''''''
    test
EOT;

$filterChain = new FilterChain();

// 多个接受者(filter)都有机会处理请求(msg), 对象组合方式生成不同的过滤链(filterChain)

$filterChain->addFilter(new HtmlFilter)->addFilter(new DbFileter);

$resourceProcessor = new ResourceProcessor($msg,$filterChain);

// echo $resourceProcessor->process();$resourceProcessor2

$filterChain2 = new FilterChain();

$filterChain2->addFilter(new DbFileter);

$resourceProcessor2 = new ResourceProcessor($msg,$filterChain2);

// 请求者入口在(ResourceProcessor), 而不在filterChain, 避免发送者(msg)和接收者(filterChain)之间的耦合关系

echo $resourceProcessor2->process();