phalapi-进阶篇2(DI依赖注入和单例模式)

#phalapi-进阶篇2(DI依赖注入和单例模式)#

##前言## 先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个优秀的开源框架.

离上一次更新过去了快两周,在其中编写了一个关于DB分表分库解决大数据量的拓展,有兴趣的童鞋可以了解了解.废话不多说,本小节在于解释一下在PhalApi框架中两个比较好的思想,单例模式和依赖注入.

附上:

官网地址:http://www.phalapi.net/

开源中国Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release

##1. 单例模式##

单例模式对于长期进行过面向对象编程的童鞋应该不算陌生,在学习php的童鞋也应该有听过,这里简单的聊一聊单例模式到底是一个怎么样东西,解决了什么问题,并且在PhalApi中是如何实现的.

单例单例,所谓单例也就是有且只有一个存在,这就是单例,不难看出他的好处资源利用少因为只有一个,大家都是知道要使用一个类必须要实例他也就是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 欢迎大家的加入!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏极客编程

基于Node.js的自动化工具Gulp

gulp是前端开发过程中一种基于流的代码构建工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;...

2351
来自专栏Python小屋

Python内置函数eval()用法及其安全问题

Python内置函数eval()用来对表达式进行求值: >>> eval('3+5') 8 >>> a = 3 >>> b = 5 >>> eval('a+b'...

1.1K9
来自专栏Android 研究

Android Handler机制1之Thread

每一个进程都有自己的独立的一块内存空间、一组资源系统。其内部数据和状态都是完全独立的。进程的优点是提高CPU的运行效率,在同一个时间内执行多个程序,即并发执行。...

1362
来自专栏从零开始学 Web 前端

从零开始学 Web 之 ES6(一)ES5严格模式

除了正常运行模式,ECMAscript 5添加了第二种运行模式:"严格模式"(strict mode)。顾名思义,这种模式使得Javascript在更严格的条件...

1082
来自专栏DOTNET

【翻译】MongoDB指南/聚合——聚合管道

【原文地址】https://docs.mongodb.com/manual/ 聚合 聚合操作处理数据记录并返回计算后的结果。聚合操作将多个文档分组,并能对已分组...

32610
来自专栏丑胖侠

《Drools7.0.0.Final规则引擎教程》第4章 4.2 activation-group& dialect& date-effective

activation-group 该属性将若干个规则划分成一个组,统一命名。在执行的时候,具有相同activation-group 属性的规则中只要有一个被执行...

23510
来自专栏idba

轻量级分布式任务调度系统-RQ

一 前言 Redis Queue 一款轻量级的P分布式异步任务队列,基于Redis作为broker,将任务存到redis里面,然后在后台执行指定...

3593
来自专栏java一日一条

怎样处理InterruptedException

Java 中的受检查异常 InterruptedException 如何处理是令人头痛的问题,下面是我对处理这个问题的理解。

1612
来自专栏深度学习计算机视觉

java多线程通信方式

1、同步 通过synchronized关键字这种方式来实现线程间的通信。 (学Linux的时候学过共享内存通信,在C中通过全局变量也行,虽然java木有) ...

3885
来自专栏码洞

Spark通信原理之Python与JVM的交互

我们知道Spark平台是用Scala进行开发的,但是使用Spark的时候最流行的语言却不是Java和Scala,而是Python。原因当然是因为Python写代...

1191

扫码关注云+社区

领取腾讯云代金券