2011-02-14 40 views
0

我想創建我自己的一種輕量級的OOP方式來跟蹤加載的文件及其相應版本(尚未實現)在我的PHP框架中,以便能夠輕鬆測試將來的依賴性問題。創建單身 - 這真的是對的嗎?

這裏是我當前的代碼,但作爲一個總的初來乍到OOP和模式,我不能確定我是否已經完成了正確的單身與否:

class loadRegistry { 

    private static $registry = null; 

    private function __construct(){ 

     if (is_null(self::$registry)); 
     self::$registry = array(); 

    } 

    public static function get() { 
     return self::$registry; 
    } 

    public static function set($filename){ 

     if (isSet(self::$registry[$filename]) AND !empty($filename)) { 
      throw new Exception("File already loaded"); 
     } 
     else self::$registry[$filename] = ''; 
    } 

} 

loadRegistry::set('filename'); 
loadRegistry::set('filename2'); 

$reg = loadRegistry::get(); 
+0

這不是一個單身人士。我不確定它試圖成爲什麼......它幾乎看起來像一個抽象工廠,但我看不到對象在哪裏處理。更何況你可以只做'private static $ registry = array()`並保存is_null檢查...並且你沒有辦法實例化它,所以沒有任何註冊表...... – ircmaxell 2011-02-14 22:23:56

+4

你可能想要讀取[靜態方法vs單例:不選擇](http://www.phparch.com/2010/03/static-methods-vs-singletons-choose-neither/)。 – 2011-02-14 22:26:28

+1

*(相關)* [爲什麼單身人士在PHP中沒有用處](http://gooh.posterous.com/singletons-in-php)是我對[誰需要單身人士]的答案的更長版本(http:// stackoverflow.com/questions/4595964/who-needs-singletons/4596323#4596323) – Gordon 2011-02-14 22:38:10

回答

2

不,它不是單例。你實際上只是在玩靜態屬性。一個單身會更喜歡這樣的:

class Registry { 

    private static $registry = null; 
    private $data; 

    private function __construct(){ 
     $this->data = array(); 
    } 

    public static function getInstance() { 
     if (is_null(self::$registry)) { 
      self::$registry = new Registry(); 
     } 
     return self::$registry; 
    } 

    public function set($filename){ 
     if (isset($this->data[$filename]) && !empty($filename)) { 
      throw new Exception("File already loaded"); 
     } 
     else { 
      $this->data[$filename] = ''; 
     } 
    } 

    // further **instance** methods 
} 

$reg = Registry::getInstance(); 
$reg->set('filename'); 
$reg->set('filename2'); 

我不知道你是否可以設置構造函數在PHP私人...我不這麼認爲。

靜態類$和一個單間的差異。單例允許一次只有一個實例。對於靜態類,你甚至不需要一個實例。另外,靜態屬性在類的所有實例之間共享(在你創建實例的情況下)。

如果您不需要實例來保存某些狀態,通常會使用靜態類。

$:沒有真正的靜態類。只有成員可以被定義爲靜態。我想說一個只有靜態成員的類可以被稱爲靜態類。

1

這段代碼看起來很奇怪 - 首先,構造函數永遠不會被任何內部函數調用,因爲它是私有的,所以不能在外部調用。這不是一個單身人士,因爲單身人士實際上是要作爲一個物體來創造,而這個階級從來就不是。

但是,您可以使用這樣的代碼來創建劃分的全局存儲,如果這是您想要做的。

下面是你單身:

class Singleton { 
    private static $me; 

    private function __construct 
    { 
     /* something */ 
    } 

    public static getInstance() 
    { 
     if(empty(self::$me)) self::$me = new self; 
     return self::$me; 
    } 

}

這裏的改進5.3+單:

class Singleton { 
    private static $me; 

    private function __construct 
    { 
     /* something */ 
    } 

    public static getInstance() 
    { 
     if(empty(self::$me)) self::$me = new static; 
     return self::$me; 
    } 

}

2

你提出什麼上面不繼單身的模式。一個Singleton只允許一個類的單個實例同時存在(與定義一個Static對象不同,它不會阻止你從同一時間創建其他對象並將它們混合起來)。

您可以在官方手冊中閱讀PHP中的Singleton模式; http://php.net/manual/en/language.oop5.patterns.php

上面的手冊示例給出了一個準系統示例,但從PHP5發佈以來,我從來沒有真正需要在PHP中使用Singleton。它們對iPhone等設備更有用,因爲您只需要一個指定的硬件接口 - 比如屏幕。不過,我想你可能會用它在你的數據庫連接中的一個PHP應用程序...

0

我看到這是有點舊..但是..

我以前只是爲了單實例而使用單例,但是在註冊表中你不再需要靜態。 另一方面是如何實施和使用註冊管理機構,以確定註冊管理機構解決方案是否良好。

因爲我使用MVC,只需要爲基礎控制器傳遞一次註冊表,一次爲基礎模型傳遞註冊表,這就是全部。另一方面,如果有一個設計需要經常傳遞註冊表對象,它可能不是一個好主意。

的基本思路是:

  1. 有一個註冊表

  2. 在非常begining僅創建數據庫類的實例,這樣一來我們不創建連接等煩。我使用了兩個數據庫,直到veri第一次我需要它時才創建連接。

    $ registry-> dbManager = new dbManager();

  3. 將註冊表對象傳遞給路由器,控制器和模型基類註冊表無處不在。
    $ registry = My_Registry :: singleton(); $ registry-> router = new router($ registry); $ registry-> dbManager = new dbManager(); 等..................

  4. DB類撐正常類,這僅僅是從DB類

    類dbManager {

    的一部分
    //DB Connections 
    private $Internal_db_con = null; 
    private $Business_db_con = null; 
    
    //DB Connection Parameters 
    private $host=null; 
    private $user=null; 
    private $pass=null; 
    
    //DB Names 
    private $internal_db_name=null; 
    private $business_db_name=null;  
    
    // 
    private $result = null; 
    
    
    
    // only one object created 
    public function __construct() 
    { 
         include_once __SITE_PATH . 'includes/db_config.inc'; 
    

    list($ this-> host,$ this-> user,$ this-> pass,$ this-> internal_db_name,$ this-> business_db_name)= $ db_conf;

    } 
    
    
    
    
    //set internal database connection 
    private function setInternalDBCon() 
    { debug('setInternalDBCon called'); 
          try{  
           # MySQL with PDO_MYSQL 
           $dbq="\""; 
           $this->Internal_db_con = new 
    

    PDO( 「MySQL的:主機=」。$這個 - >主機 「; DBNAME =」 $這 - > internal_db_name,$這 - >用戶,$這 - >通, 陣列(PDO :: MYSQL_ATTR_INIT_COMMAND =>「SET NAMES utf8」));

    $this->Internal_db_con->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
           } 
          catch(PDOException $e) 
          { 
          echo 'Error connecting to MySQL: ' .$e->getMessage(); 
          }  
    
    } 
    
    
    
    
    
    
    //set business database connection 
    public function setBusinessDBCon() 
    { 
          try{  
          # MySQL with PDO_MYSQL 
          $dbq="\""; 
          $this->Business_db_con = new 
    

    PDO( 「MySQL的:主機=」。$這個 - >主機 「; DBNAME =」 $這 - > internal_db_name,$這 - >用戶,$這 - >通, 陣列(PDO :: MYSQL_ATTR_INIT_COMMAND =>「SET NAMES utf8」));

    $ this-> Business_db_con-> setAttribute(PDO :: ATTR_ERRMODE,PDO :: ERRMODE_EXCEPTION); }
    catch(PDOException $ e) {
    echo'連接到MySQL的錯誤:'。$ e-> getMessage();
    }

    } 
    
    
    
    
    
    
    /*check if a row exists in a safe way that avoids sql atack*/ 
    public function uniqueRowExists($dbcon, $table,$col_name, $data) 
    {  
         //check if connection is set 
         if($this->{$dbcon.'_db_con'}==null) //dynamic variable call 
        $this->callMyFunc('set'.$dbcon.'DBCon'); //dynamic function call 
    

    .......................等....

     //prepare 
         $stmt = $this->{$dbcon.'_db_con'}->prepare($sql); 
        $stmt->execute($data); 
    

    ..... ............等

  5. 這是我如何調用一個公共職能從DB類

    //查詢數據庫
    $結果= $這個 - >登記處送交> dbManager-> uniqueRowExists ( '內部',「 internal_user',Array('uname','pass'),$ input); //連接到來自表,coloumns,陣列數據選擇搜索

這種方式只有一個實例的任何地方。