设计模式(PHP)

 

设计模式是对典型问题的典型解决方案,是一种套路。比如说前端如何写选项卡,如何在网页弹窗,都是有固定套路的,前辈们都总结出来了,我们学会就好。

开发中所谓的“面向接口开发”,涉及到“调用”的概念。服务器端和客户端由不同的人员开发,但是不必要互相认识,开发的时候只需要对接口负责,就能够共同合作完成任务。生产插座的厂商和电器厂商并不是互相了解,但是只各自遵循插座插头规范,就能够做出可用的产品。

 

简单工厂

<?php

//客户端和服务器端共同的接口
interface db{
    function conn();
}

//服务端开发,不知道将会被谁调用
class dbmysql implements db{
    public function conn(){
        echo '连接上了Mysql';
    }
}

class dbsqlite implements db{
    public function conn(){
        echo '连接上了sqlite';
    }
}
//简单工厂
class Factory{
    public static function createDB($type){
        if ($type=='mysql') {
            return new dbmysql();
        }
        else if($type == 'sqlite'){
            return new dbsqlite();
        }
        else{
            throw new Exception('错误的数据库类型');
        }
    }
}

//客户端,不知道服务端到底有哪些类,只知道对方开放了一个Factory::createDB方法,并且方法允许传递数据库名称
$mysql = Factory::createDB('mysql');
$mysql->conn();

$sqlite = Factory::createDB('sqlite');
$sqlite->conn();

从上面的代码中可以看出来,如果服务端要新增一个oracle类型,根据开闭原则(对于修改是封闭的,对于扩展是开放的),在不修改服务端源代码的情况下,是不容易做到的。

工厂方法:

<?php

//客户端和服务器端共同的接口
interface db{
    function conn();
}

interface Factory{
    function createDB();
}

//服务端开发,不知道将会被谁调用
class dbmysql implements db{
    public function conn(){
        echo '连接上了Mysql';
    }
}

class dbsqlite implements db{
    public function conn(){
        echo '连接上了sqlite';
    }
}

class mysqlFactory implements Factory{
    public function createDB(){
        return new dbmysql();
    }
}    
class sqliteFactory implements Factory{
    public function createDB(){
        return new dbsqlite();
    }
}

//服务端添加oracle类
class dboracle implements db{
    public function conn(){
        echo '连接上了orecle';
    }
}

class oracleFactory implements Factory{
    public function createDB(){
        return new dboracle();
    }
}

//客户端开始

$fact = new mysqlFactory();
$db = $fact->createDB();
$db->conn();

$fact = new sqliteFactory();
$db = $fact->createDB();
$db->conn();

$fact = new oracleFactory();
$db = $fact->createDB();
$db->conn();

 单例模式。当我们需要数据库对象,cookie对象或者upload对象的时候,通常需要用到单例模式。

 实现思路:封闭外部的new操作,内部可以new,如果有,就直接返回,没有就new出来。最后再防止外部覆盖或者克隆。

<?php

class single{
    protected static $ins = null;
    public static function getIns(){
        if (self::$ins === null) {
            self::$ins = new self();
        }
        return self::$ins;
    }
    final protected function __construct(){

    }
    final protected function __clone(){

    }
}

观察者模式

用javascript实现观察者模式

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>用观察者模式切换页面风格</title>
<style>
div{
    float: left;
    width: 200px;
    height: 200px;
    margin: 10px;
    border: 1px solid black;
}
</style>
<script>
window.onload = function(){
    //服务端
    var oSwitch = document.getElementById('switch');
    oSwitch.observers = {};
    oSwitch.attach = function(key,obj){
        this.observers[key] = obj;
    };
    oSwitch.detach = function(key){
        delete this.observers[key];
    };
    oSwitch.onchange = oSwitch.modify = function(){
        //这里还是很关键的
        for(var key in this.observers){
            this.observers[key].update(this);
        }
    };
    //客户端
    var oColor = document.getElementById('color');
    var oAd = document.getElementById('ad');
    oColor.update = function(observe){
        if (observe.value == 'male') {
            this.style.background = 'gray';
        }
        else if(observe.value == 'female'){
            this.style.background = 'pink';
        }
    }
    oAd.update = function(observe){
        if (observe.value == 'male') {
            this.innerHTML = '汽车';
        }
        else if(observe.value == 'female'){
            this.innerHTML = '化妆品';
        }
    }

    //观察select的变化
    oSwitch.attach('color',oColor);
    oSwitch.attach('ad',oAd);

    //如果要扩展hobby
    var oHobby = document.getElementById('hobby');
    oHobby.update = function(observe){
        if (observe.value == 'male') {
            this.innerHTML = '爱好是打篮球';
        }
        else if(observe.value == 'female'){
            this.innerHTML = '爱好是逛街';
        }
    }

    //观察爱好
    document.getElementById('confirm').onclick = function(){
        oSwitch.attach('hobby',oHobby);
    };
    document.getElementById('cancel').onclick = function(){
        oSwitch.attach('hobby');
    };
};
</script>
</head>
<body>
    <select name="" id="switch">
        <option value="male">男士风格</option>
        <option value="female">女士风格</option>
    </select>
    <input type="button" value="观察爱好" id="confirm">
    <input type="button" value="取消观察爱好" id="cancel">
    <div id="color">我是颜色</div>
    <div id="ad">我是广告</div>
    <div id="hobby">我是爱好</div>
</body>
</html>

用php实现观察者模式

 

<?php

//PHP5中提供了观察者observer与被观察者subject的接口
class user implements SplSubject{
    public $times;
    public $hobby;

    protected $observers = null;
    public function __construct($hobby){
        $this->times = rand(1,10);
        $this->hobby = $hobby;
        $this->observers = new SplObjectStorage();
    }
    public function login(){
        //操作session
        $this->notify();
    }
    public function attach(SPLObserver $observer){
        $this->observers->attach($observer);
    }
    public function detach(SPLObserver $observer){
        $this->observers->detach($observer);
    }
    public function notify(){
        $this->observers->rewind();
        while ($this->observers->valid()) {
            $observer = $this->observers->current();
            $observer->update($this);
            $this->observers->next();
        }
    }
}


class security implements SPLObserver{
    public function update(SplSubject $subject){
        if ($subject->times < 3) {
            echo '这是第'.$subject->times.'次安全登陆'.'<br/>';
        }
        else{
            echo '这是第'.$subject->times.'次登陆,异常'.'<br/>';
        }
    }
}

class ad implements SPLObserver{
    public function update(SplSubject $subject){
        if ($subject->hobby == 'sports') {
            echo '台球世锦赛';
        }
        else{
            echo '好好学习';
        }
    }
}


//实施观察
$user = new user('sports');
$user->attach(new security());
$user->attach(new ad());

$user->login();
?>

 

职责链模式

 

posted @ 2016-11-14 10:38  建彬  阅读(251)  评论(0编辑  收藏  举报