注冊者模式 (registry) 提供了一種機制,能讓你在程式中有條理的存放并管理對象 (object) ,它的主要作用是防止使用者濫用全局對象 (global object) 。
Registry 通常提供對象的存取,登出等方法,友善使用者管理。下面來看看 Zend Framework 中 registry 的例子,這裡挑選最經典的 Zend_Registry 為例 :
class Zend_Registry extends ArrayObject
{
......
// Registry 私有對象是用來存儲共享對象的注冊者
private static $_registry = null;
// Constructor 初始化為 ArrayObject 對象
// @link http://www.php.net/manual/en/class.arrayobject.php
public function __construct($array = array(), $flags = parent::ARRAY_AS_PROPS)
{
parent::__construct($array, $flags);
}
// 傳回預設的注冊對象執行個體
public static function getInstance()
{
if (self::$_registry === null) {
self::$_registry = new Zend_Registry();
}
return self::$_registry;
}
// 銷毀注冊者
public static function _unsetInstance()
{
self::$_registry = null;
}
// Getter 方法,基于 ArrayObject 的 offsetGet() 方法,提取存儲的執行個體。
public static function get($index)
{
$instance = self::getInstance();
...
return $instance->offsetGet($index);
}
// Setter 方法,基于 ArrayObject 的 offsetSet() 方法,存儲執行個體。
public static function set($index, $value)
{
$instance = self::getInstance();
$instance->offsetSet($index, $value);
}
......
}
上面是經過簡化而得的源代碼,值得注意的是 Zend_Registry 繼承自 ArrayObject ,也就是說 Zend_Registry 完全能以數組的形式來進行操作。
以下的用法在本質上是一樣的 :
Zend_Registry::set($name, $value);
......
$value2 = Zend_Registry::get($name);
$registry= Zend_Registry::getInstance();
$registry[$name] = $value;
......
$value2 = $registry[$name];
另外 registry 通常可以與單元子模式 singleton 搭配使用 (singleton - 參見 "Zend Framework 與設計模式(一) - singleton 單元子模式"一章),例如 :
class singletonExample
{
...
// Singleton 單元子對象
public static function getInstance()
{
if (false == Zend_Registry::isRegistered('singletonExample')) {
Zend_Registry::set('singletonExample', new self());
}
return Zend_Registry::get('singletonExample');
}
...
}
在 Zend_Framework 中,Zend_Registry 還扮演了架構建構者的角色。例如在 Zend_View_Helper_Translate 中,Zend_Registry 為翻譯器 (translate) 視圖助手提供了預設的翻譯者 (translator) :
class Zend_View_Helper_Translate extends Zend_View_Helper_Abstract
{
...
// 擷取翻譯對象
// 如果目前沒有設定翻譯者,則嘗試從注冊者中根據關鍵詞 Zend_Translate 來尋找
public function getTranslator()
{
if ($this->_translator === null) {
require_once 'Zend/Registry.php';
if (Zend_Registry::isRegistered('Zend_Translate') === true) {
$this->setTranslator(Zend_Registry::get('Zend_Translate'));
}
}
return $this->_translator;
}
...
}