#phalapi-进阶篇2(DI依赖注入和单例模式)#php
##前言## 先在这里感谢phalapi框架创始人@dogstar,为咱们提供了这样一个优秀的开源框架.java
离上一次更新过去了快两周,在其中编写了一个关于DB分表分库解决大数据量的拓展,有兴趣的童鞋能够了解了解.废话很少说,本小节在于解释一下在PhalApi框架中两个比较好的思想,单例模式和依赖注入.git
附上:web
官网地址:http://www.phalapi.net/spring
开源中国Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release编程
##1. 单例模式##设计模式
单例模式对于长期进行过面向对象编程的童鞋应该不算陌生,在学习php的童鞋也应该有听过,这里简单的聊一聊单例模式究竟是一个怎么样东西,解决了什么问题,而且在PhalApi中是如何实现的.api
单例单例,所谓单例也就是有且只有一个存在,这就是单例,不难看出他的好处资源利用少由于只有一个,你们都是知道要使用一个类必需要实例他也就是new在每次new一个对象的时候都会在内存中生成一块区域来存放这个实例,若是在程序一次运行中使用了不少的new实例化了同一个对象,那就比较消耗资源了,可是若是是通用一个使用全局变量global程序又会显得不优雅并且会很乱,在这种状况下单例模式就产生了.数组
单例模式就是一个一箭双鵰的一个方法既能够全局通用,二不用担忧占用过多的资源,三又很是优雅,咱们来一块儿看看在PhalApi中是如何实现单例模式的:框架
//你们看到咱们经常使用的DI方法内部实现的是PhalApi_DI中的静态方法one方法 function DI() { return PhalApi_DI::one(); }
而后咱们看向one方法内部
每当咱们请求过来的时候先验证静态变量instance是否是没有被初始化,若是是第一次调用他会在内部去实例化PhalApi_DI类而后负值给**$instance**而后返回实例好的这个静态变量,当咱们下次在请求过来的时候这个静态变量已经被实例化好了就会直接跳过实例的过程直接返回这个对象,也就是咱们在PhalApi框架全部的地方使用的DI方法其实都是一个对象,在内存中只存在一块区域,代码以下:
public static function one(){ if(self::$instance == NULL){ self::$instance = new PhalApi_DI(); self::$instance->onConstruct(); } return self::$instance; }
其实不难咱们只用吧new一个类的操做封装到咱们须要new的类的静态方法在向上面同样的去判断,就能够很简单的去实现单例模式.
##2. 依赖注入##
依赖注入又称之为**"控制反转",若是是熟悉javaweb开发的spring**框架应该有比较深的感触,在这里也不往深的讲,就简单讲解一下PhalApi中DI依赖注入的实现让你们了解这种设计模式如何实现以及自此基础上实现的惰性加载机制.
###2.1 DI依赖注入实现###
你们在PhalApi中经常使用的DI()方法,也就是采用咱们上面所谓的单例模式不用多说了,也就是咱们每次使用DI()其实就是在使用PhalApi_DI类,那么咱们依赖注入的关键也就是在PhalApi_DI之中
先来说一下他的一个实现方式在来说具体实现,这里举个例子:
//配置 DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');
其实在内部有一个数组,它吧config做为了key,吧new PhalApi_Config_File(API_ROOT . '/Config')做为了value而后保存了起来当咱们下一次使用DI->config->get();的时候它就会根据key值config拿出开始new好的类,因此能够说config操做是依赖于DI(),并且在使用DI()->config的时候永远都是在使用的一个实例,也能减小资源的消耗.
有的童鞋就好奇了为何DI()->config会存到数组须要的时候会拿出来呢,感兴趣的童鞋能够百度一下魔法方法**__ser和__get**
/**你们能够看到这是PhalApi_DI中的魔法方法__set * 也就是当使用DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');的时候 * 得到的name值就是config,得到的value也就是new PhalApi_Config_File(API_ROOT . '/Config'); */get同理,在内部实现都是调用了内部get和set方法 public function __set($name, $value){ $this->set($name, $value); } public function __get($name){ return $this->get($name, NULL); }
看完以后你们是否是以为很简单啊,你们之后也能够在本身设计类的时候采用这种灵活的魔法方法实现.
###2.2 惰性加载###
在PhalApi中的DI()方法也提供惰性加载,惰性加载如字意也就是当类没有被使用到的时候不会加载,这样的操做也是为了不浪费没必要要的资源,当咱们不是用的时候永远不会去实例化只有当你使用到的时候才会去new这个类而后实例化以后使用,咱们来看看是如何实现的.
//当咱们执行如下语句的时候,在依赖注入的时候存的是value值是字符串的test DI()->test = 'test'; //使用DI()->test->test();的时候会使用到PhalApi中的get方法,在get方法中有一段代码 $this->data[$key] = $this->initService($this->data[$key]); //在initService方法内部验证了value是字符串就实例化了再返回 if($config instanceOf Closure){ $rs = $config(); }elseif(is_string($config) && class_exists($config)){ $rs = new $config(); if(is_callable(array($rs, 'onInitialize'))){ call_user_func(array($rs, 'onInitialize')); } }else{ $rs = $config; }
##3. 总结##
在本节中简单的讲解了关于单例模式,依赖注入以及惰性加载,这几种设计模式都是经常使用的能后减小资源利用率的有效的方法,但愿你们看了这篇介绍可以实地的去体验一下PhalApi中的这几种模式,在下一小节就讲解如何构建本身的拦截器,但愿你们可以持续关注!
注:笔者能力有限有说的不对的地方但愿你们可以指出,也但愿多多交流!
官网QQ交流群:421032344 欢迎你们的加入!