php设计模式

1.控制反转(IOC)

 使用IOC的:

优点:消除对象之间的耦合关系,提高代码的灵活性,从而加快开发速度,提升代码质量

缺点:在真实框架中,由于会使用反射机制,会降低代码的运行速度,如果对速度很敏感,就不适合使用IOC了.

 以下是我整理的注释加强印象加深版代码,其中的bind其实就是工厂模式的一种体现

<?php
class Superman{
    function __construct($skill){
        //print_r($skill);
    }
}
class XPower{
    function __construct(){
        //echo __CLASS__.PHP_EOL;
    }
}

class Container
{
    protected $binds;
 
    protected $instances;
 
    public function bind($abstract, $concrete)
    {
        if ($concrete instanceof Closure) {
            $this->binds[$abstract] = $concrete;
        } else {
            $this->instances[$abstract] = $concrete;
        }
    }
     //make方法其实是传入参数,调用已经绑定的闭包/方法,为什么使用call_user_func_array?因为参数个数未知,使用call_user_func_array会更灵活
    public function make($abstract, $parameters = [])
    {
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }
 
        array_unshift($parameters, $this);//必须有一个container参数,因为很有可能在make时使用container
        return call_user_func_array($this->binds[$abstract], $parameters);
    }
}

// 创建一个容器(后面称作超级工厂)
$container = new Container;
 
// 向该 超级工厂 添加 超人 的生产脚本(告诉容器待会如何生产对象)
$container->bind('superman', function($container, $moduleName) {
    return new Superman($container->make($moduleName));
});
 
// 向该 超级工厂 添加 超能力模组 的生产脚本(告诉容器待会如何生产对象)
$container->bind('xpower', function($container) {
    return new XPower;
});
 

 
// ******************  华丽丽的分割线  **********************
// 开始启动生产
$superman_1 = $container->make('superman', ['xpower']);//生产对象,用的是刚刚绑定的方法

 2.单例模式

在整个应用生命周期内,对某个类,只实例化一次,应用场景为:连接数据库,记录日志,使用单例模式可以避免不必要的资源消耗

<?php
class Singleton{
    private static $obj=null;
    private function __construct(){}
  private function __clone(){}
  
  

    static function getInstance(){
        if(!self::$obj){
            self::$obj=new self;
        }
        return self::$obj;
    }
}
$res=Singleton::getInstance();
$res2=Singleton::getInstance();
$res3=Singleton::getInstance();
var_dump($res);
var_dump($res2);
var_dump($res3);

 3.工厂模式

工厂模式用于生产对象,在最原始的代码中,如果一个对象obj1需要另一个对象obj2,通常是在obj1内部new一个obj2,但是这种硬性的编码很不灵活,比如因需求改变,要使用另一个和obj2功能类似的obj3,或者obj2修改了类名,这样会使代码改动很大

使用工厂模式,可以让obj1只使用工厂Factory得到对象obj2,obj3,obj4...

工厂模式解除了obj1与obj2的耦合关系,使代码便于修改.实现了低耦合.

在上面例1中IOC容器的binds属性,其实就是工厂模式的体现.通过对ioc容器对象bind方法的调用,得到了许多小车间(new各种类的闭包函数),车间装载完毕,在使用make方法时就会根据参数使用相应车间..

4.观察者模式

 将触发事件(发布者)与发生事件后需要执行的动作(订阅者需要做的动作)解耦

目的:代码更灵活,大大提升可维护性

 

<?php
/**
 * Created by PhpStorm.
 * User: zhudong
 * Date: 16/8/11
 * Time: 下午4:02
 */
class Newspaper implements SplSubject {
    private $name;
    private $observers;
    private $content;
    public function __construct($name){
        $this->$name = $name;
        $this->observers = new SplObjectStorage();
    }
    public function attach(SplObserver $observer){
        $this->observers->attach($observer);
    }
    public function detach(SplObserver $observer){
        $this->observers->detach($observer);
    }
    public function notify(){
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
    public function getContent(){
        return $this->content."{$this->name}";
    }
    public function breakOutNews($content) {
        $this->content = $content;
        $this->notify();
    }
}



//不同的观察者,对新闻做出不同的反应,此处举例Reader和Reader2
class Reader implements SplObserver {
    private $name;
    public function __construct($name){
        $this->name = $name;
    }
    public function update(SplSubject $subject) {
        echo $this->name.' received breakout news'.$subject->getContent().'and say 不错~~'.PHP_EOL;
    }
}

class Reader2 implements SplObserver {
    private $name;
    public function __construct($name){
        $this->name = $name;
    }
    public function update(SplSubject $subject) {
        echo $this->name.' received breakout news'.$subject->getContent().'and say 垃圾!'.PHP_EOL;
    }
}



$newspaper = new Newspaper('齐鲁晚报');
$allen = new Reader("allen");
$jimmy = new Reader("mike");
$tom = new Reader2("tom");
$jerry = new Reader2("jerry");
$newspaper->attach($allen);
$newspaper->attach($jimmy);
$newspaper->attach($tom);
$newspaper->attach($jerry);
$newspaper->detach($jerry);

$newspaper->breakOutNews('本报讯...');
        

 参考资料

对依赖注入和控制反转的说明文

laravel 学习笔记 —— 神奇的服务容器

实际开发中哪些场景需要用到观察者模式?

php常见三种设计模式

posted @ 2017-12-11 18:31  toDoYourBest  阅读(129)  评论(0编辑  收藏  举报