2010-01-20 72 views
10

我正在使用PHP類和對象。在這個問題中,字段和方法的名字就是爲了讓你知道我在說什麼。PHP中的註冊表或Singleton模式?

它與使用單和註冊表的設計模式。

現在可以說,我需要訪問數據庫對象,緩存對象,核心設置對象,Session對象在幾乎所有其他I類將需要訪問這些。所以我會使用註冊表將這些對象的全部4個存儲到1個註冊表類對象中。然後,我可以將easiyl傳遞給我需要訪問這些對象的任何其他對象。所以這聽起來很好,但如果我有一些不需要全部4個對象的類,如果我只需要訪問數據庫對象或某些其他類中的Session對象,該怎麼辦?對於性能來說,最好是在這些其他對象中使用一個單例,還是繼續使用我的註冊表?

我不知道不夠好對象在PHP中是如何工作的知道是否會有任何形式的performnce增益(使用更少的內存,CPU使用率,加載時間)。

因此,任何人有經驗,在此也許可以告訴我,如果有會使用一個或其他任何收益,我的階段,我可以去醚方式又不影響生產時間或任何東西。如果我現在可以,我想用最好的方法。

+0

我居然發現一個問題,剛纔說是basicly相同http://stackoverflow.com/questions/1967363/registry-or-singleton – JasonDavis

+0

請注意,如果您正在使用PHP4或PHP5的對象...工作方式非常不同,而在PHP4中,不支持「static」這樣的關鍵字。 機會是你使用5,但如果你想進入相關的面向對象,你需要確定。 –

回答

3

這取決於你的應用。如果你仍然需要4個類中的3個,那麼使用註冊表比單獨處理3個更爲理想,因爲你不需要第四個。懶惰地加載類將是減少內存佔用量的一種方法,但是隨後您需要指示註冊表何時創建對象,並且與處理單例相比沒有多大區別。或者,您可以創建一個n參數構造函數或使用數組來指示您的註冊表在構建過程中實例化哪些類。

class Registry { 
    public $class1; 
    public $class2; 

    function __construct($uses) { 
     foreach($uses as $class) { 
      $this->{$class} = new {$class}(); 
     } 
    } 

} 

然後通過指定實例化哪一個類實例化你的註冊表。

$reg = new Registry(array('class1')); 

你顯然會希望你的構造函數來處理零個參數佔默認實例的所有類。

+0

這是一個很酷的想法,謝謝。我應該提到,即使1個類只需要1-2個對象,在同一頁面上已經有另一個類被調用,最有可能的是,所有4個對象也已經被注入到該類中。我不確定內存的東西是怎麼樣的,所以它可能已經加載了一次。我不知道內存是否會將對象存儲在內存中,或者不是。 – JasonDavis

+0

我的代碼示例假設您的類持有他們自己的註冊表實例。如果每頁使用相同的通用註冊表對象有多個類,則這將意味着大量多餘的內存。如果您使用的是靜態/全局實例,那麼您的實現將與我的示例不同,但它仍可以完成。這也意味着在所有類的內存中共享相同的對象,這會更有效率。 爲了讓我的例子以這種方式工作,使用Registry :: initInstances()函數而不是使用構造函數。 –

+0

好吧,我在想什麼,猜想我們在同一頁面,有點像下面的dbemerlin的方法。 – JasonDavis

4

您可以實現延遲加載只加載你真正需要的對象:

class Registry 
{ 
    private static $database = null; 

    private static function connectDatabase($key) 
    { 
     [... do connection stuff ...] 
    } 

    public static function getDatabase($key) 
    { 
     if (Registry::$database == null) 
     { 
      Registry::connectDatabase($key); 
     } 
     return Registry::$database; 
    } 
} 

登記數據庫連接參數的代碼留給讀者做練習。

+3

這不就是一個單身嗎? – JasonDavis

+0

我不知道還有什麼可以稱爲單身 –

+0

這是純粹的單身模式,這不是真正的模式,而是反模式。 –

1

也許,這是正確的辛格爾頓,註冊模式。 OFC,你可以實現不同的東西,SplFixedArray,ArrayAccess接口等等。加入破壞和破壞內部物體以確保不泄漏也是不錯的。

class oRegistry{ 
    private static $instance = null; 

    private $storage = array(); 

    private function __construct(){} 

    private function __clone(){} 

    public static function getInstance(){ 
     if(self::$instance === null){ 
     self::$instance = new self(); 
     } 
     return self::$instance; 
    } 

    public function attach($name, $o) { 
     if(true === isset($this->storage[$name])) { 
      throw new Exception('The instance with name '.$name.' already exists in registry.'); 
     } 
     if(!empty($name)) { 
      $this->storage[ $name ] = $o; 
     } 
    } 

    public function detach($name){ 
     if(isset($this->storage[ $name ])) { 
      $this->storage[ $name ] = null; 
      unset($this->storage[ $name ]); 
     } 
    } 

    public function get($name){ 
     if(false === isset($this->storage[$name])) { 
      throw new Exception('Invalid instance requested'); 
     } 
     return $this->storage[ $name ]; 
    } 
} 

// usage example 
$storage = oRegistry::getInstance(); 
$obj = new stdClass; 
$obj2 = new stdClass; 
$obj->test1 = 'test'; 
$obj2->test2 = 't2'; 

$storage->attach('test1', $obj); 
$storage->attach('test2', $obj2); 

$got = $storage->get('test2'); 
var_dump($got); // object(stdClass)#3 (1) { ["test2"]=> string(2) "t2" } 

$storage->detach('test2'); 
$got = $storage->get('test2'); 
var_dump($got); // bool(false)