正文:
许多joomla的核心类中红都会用一个叫做getInstance()的方法。我们有很多种方法是使用getInstance().首先,我们将会用它来实现单件模式。
(单件模式就是我们使用某一个类的成员函数返回这个类的实例,他能够保证我们只创建一个类的实例)
下面的例子演示了我们可以用getInstance()来返回对象而不是使用类的构造函数来返回对象。
/**
* Demostrates the singleton pattern in Joomla!
*/
class SomeClass extends JObject
{
/**
* Constructor
*
* @access private
* @return SomeClass New Object
*/
function __construct(){}
/**
* Returns a reference to the global SomeClass Object
*
* @access public
* @static
* @ return SomeClass the SomeClass Object
*/
function &getInstance()
{
statice $instance;
if(!$instance)
{
$instance = new SomeClass();
}
return $instance;
}
}
在类的声明中,我们用让getInstance()方法返回一个引用。并且我们将他作为一个静态的函数。这就是说,当我们用这个方法,我们必须使用=&的操作符。因为他是静态的方法,所以需要用SomeClass::getInstance()来调用。
下面的代码演示了我们如何来使用这个类:
$anObject = & SomeClass::getInstance();
$anObject->set('foo','bar');
$anotherObject = & SomeClass::getInstance();
echo $anotherObject->get('foo');
上面的两个变量 $anObject $anotherObject都表示的是同一个对象。这也就是说最后的输出就是‘bar’.
这种机制可以允许我们去实例化一个子类。一个好的例子就是核心的JDocument .这个类可以实例化JDocumentError,JDocumentFeed,JDocumentHTMl,JDocumentPDF和JDocumentRAW(可以在libraries/joomla/document下查看原始代码)
下面的例子,我们将尝试去实现一个类似的。假设subClasses的实现文件位于组件的根目录下下,并且他的前缀是SomeClass:
/**
* Returns a reference to the global SomeClass object
*
* @access public
* @static
* @param string A string
* @return mixed A SomeClass object,false on failure
*/
function &getInstance($foo)
{
statice $instances;
// Prepare static array
if(!$instances)
{
$instances = array();
}
$foo = (string)$foo;
$class = 'SomeClass'.$foo;
$file = strtolower($foo).'.php';
if(empty($instances[$foo]))
{
if(!class_exists($class))
{
// class does not exists ,so we need to find it
jimport('joomla.filesystem.file');
if(JFile::exists(JPATH_COMPONENT.DS.$file))
{
// file found, Let's include it
require_once JPATH_COMPONENT.DS.$file;
if(!class_exists($class))
{
// file doesn't contain the class
JError::raiseEror(0,'Class'.$class. 'Not found!');
return false;
}
}
else
{
// file where the class should be not found
JError::raiseError('ERROR_CODE','File'.$file.'Not found!');
return false;
}
}
$instances[$foo] = new $class();
}
return $instance[$foo];
}
代码说明:
我们为什么要采用这种方式来获得一个类的实例呢?
- 更加容易追踪对象。就拿JDatabase 对象作为一个例子。我们可以随时访问数据库对象用JFactory::getDBO()方法。如果我们不使用这种方式,那么我们每次都需要传递这个对象或者将他申明为全局对象(在每一个需要使用的方法中都需要这么做,那将会很麻烦)。
- 减少重复性工作。我们不必每次调用都需要实例化这个对象
- 符合joomla内核标准调用方法
