在阿里一面的时候,面试官问我知道php的设计模式吗,我在面试之前只匆匆看了下工厂模式,其他都没有看,没有答上来。
面试结束后,我Google到一篇讲php设计模式很好的博客,大家感兴趣的可以看下。链接是:。
距离二面的时间有限,我只看了工厂模式,单例模式,适配器模式,和观察者模式。在看完这几个后,我突然感觉可以去尝试看下大二使用的ci框架的源码。之前因为赶项目和自己水平有限的原因,尝试查看源代码的时候,完全搞不懂框架的设计者这么写代码的意图为何。
即将大四的今天,在初步看了几个设计模式之后,我发现自己渐渐能窥探出一丝框架设计者代码的艺术感,虽然感觉自己可能是管中窥豹,但还是压抑不住这种有些豁然开朗的激动,想把这个感觉很棒的部分记录下来。
1 CodeIgniter(以下简称ci)的运行流程
ci在启动的第一步,是执行index.php文件,该文件定义了许多变量以及需要加载的模块的路径的设置,并在最后引入了/core/CodeIgniter.php,
这个文件可以说是整个ci运行的流程,有位分析ci源代码的大牛说,将这个文件运行一遍,基本上算是完成了整个CI框架的一次完成运行过程,但我在1个小时之前才去分析源代码,运行整个CI的具体流程我还不知,但是在/core/CodeIgniter.php中引用了一个公共函数文件,位于/core/Common.php
2 Common.php文件
可以看下该文件中的官方介绍:
-
/**
-
* Common Functions
-
*
-
* Loads the base classes and executes the request.
-
*
-
* @package CodeIgniter
-
* @subpackage CodeIgniter
-
* @category Common Functions
-
* @author EllisLab Dev Team
-
* @link http://codeigniter.com/user_guide/
-
*/
意思是说该文件定义了一些公共函数,用来加载基本的类和执行请求。
其中有一个&load_class的函数是整个文件的核心。
3 &load_class
以下是该函数的定义。
-
// ------------------------------------------------------------------------
-
-
if ( ! function_exists('load_class'))
-
{
-
/**
-
* Class registry
-
*
-
* This function acts as a singleton. If the requested class does not
-
* exist it is instantiated and set to a static variable. If it has
-
* previously been instantiated the variable is returned.
-
*
-
* @param string the class name being requested
-
* @param string the directory where the class should be found
-
* @param string an optional argument to pass to the class constructor
-
* @return object
-
*/
-
function &load_class($class, $directory = 'libraries', $param = NULL)
-
{
-
static $_classes = array();
-
-
// Does the class exist? If so, we're done...
-
if (isset($_classes[$class]))
-
{
-
return $_classes[$class];
-
}
-
-
$name = FALSE;
-
-
// Look for the class first in the local application/libraries folder
-
// then in the native system/libraries folder
-
foreach (array(APPPATH, BASEPATH) as $path)
-
{
-
if (file_exists($path.$directory.'/'.$class.'.php'))
-
{
-
$name = 'CI_'.$class;
-
-
if (class_exists($name, FALSE) === FALSE)
-
{
-
require_once($path.$directory.'/'.$class.'.php');
-
}
-
-
break;
-
}
-
}
-
-
// Is the request a class extension? If so we load it too
-
if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
-
{
-
$name = config_item('subclass_prefix').$class;
-
-
if (class_exists($name, FALSE) === FALSE)
-
{
-
require_once(APPPATH.$directory.'/'.$name.'.php');
-
}
-
}
-
-
// Did we find the class?
-
if ($name === FALSE)
-
{
-
// Note: We use exit() rather then show_error() in order to avoid a
-
// self-referencing loop with the Exceptions class
-
set_status_header(503);
-
echo 'Unable to locate the specified class: '.$class.'.php
该函数首先是一个单例模式的模型,当静态变量的数组中已经加载了该类,则返回引用,如果没有则引入类文件并初始化该类。调用这个函数时自始至终都是返回那个静态数组是单例的。
其次,对需要加载并且实例化的类,并不是在哪里需要的时候require_once来引入,并用new来实例化,而是类似工厂的模式,统一的进行实例化,并且存储在静态数组里,这就使得在ci运行过程中同样一个类只被实例化了一次。
最后,Common.php中还定义了一个&is_loaded的函数,用来记录已经被初始化的类,代码如下:
-
if ( ! function_exists('is_loaded'))
-
{
-
/**
-
* Keeps track of which libraries have been loaded. This function is
-
* called by the load_class() function above
-
*
-
* @param string
-
* @return array
-
*/
-
function &is_loaded($class = '')
-
{
-
static $_is_loaded = array();
-
-
if ($class !== '')
-
{
-
$_is_loaded[strtolower($class)] = $class;
-
}
-
-
return $_is_loaded;
-
}
-
}
该方法也是使用一个单例,使用静态数组保存已经加载的类,我感觉有些观察者模式的思想。它跟踪着已经加载的类的状态。
阅读(1876) | 评论(0) | 转发(0) |