2013-02-04 45 views
3

使用單例模式時是否存在差異?在類中保存靜態實例並將其保存在返回實例的方法中時是否有任何區別?在類方法中使用靜態實例還是在類中使用

例子: 課內。

class cExampleA { 
    static $mInstance; 

    protected function __construct() { 
     /* Protected so only the class can instantiate. */ 
    } 

    static public function GetInstance() { 
     return (is_object(self::$mInstance) ? self::$mInstance : self::$mInstance = new self()); 
    } 
} 

返回方法裏面。

class cExampleB { 
    protected function __construct() { 
     /* Protected so only the class can instantiate. */ 
    } 

    static public function GetInstance() { 
     static $smInstance; 
     return (is_object($smInstance) ? $smInstance : $smInstance = new self()); 
    } 
} 

在一個側面說明,使用三元運算符的例子有效(這意味着它可能會導致問題),並沒有任何好處/倒臺使用is_object超過isset?

更新:似乎唯一的區別是靜態實例的範圍?

+0

,在跳出我這裏的是,在照例a,靜態屬性是公開訪問的主要事情。我猜這不是你想要的,所以你應該把它設置爲'private'(尤其是因爲你只用'is_object()'來檢查它,這意味着它可以被任何東西覆蓋。會更安全)。 – SDC

+0

是的,我剛剛錯過了私人。 instanceof聽起來像個好主意,我總是忘記它。 – James

+0

我必須說實話,我不知道在這種情況下是有區別的。我想這是其中有不止一種方法來實現同樣的事情的情況之一。除非有人能以其他方式告訴我一個理由。對我來說,我會堅持使用私有財產(即exampleA),但我看不出爲什麼exampleB是錯誤的任何理由。 – SDC

回答

1

有趣的問題。就行爲而言,據我所知,這兩個例子之間沒有任何區別(範圍除外)。

PHP是一種鬆散類型的編程語言,因此您甚至可以在示例A中全部省略類屬性聲明。而對於鬆散類型的語言,似乎總有更多的方法實現相同的功能!

真正的問題很快就會變成設計模式之一(在這種情況下是數據封裝),以確保我們編寫的代碼遵循由我更聰明的人設計的慣例!

在這個例子中,類應該擁有它的屬性,並適當地設置該屬性的範圍(在這種情況下是私有的)並提供邏輯存取方法。

這是我會怎麼寫呢:

class ExampleA 
{ 
    static private $_instance = null; 

    private function __construct(){} 

    static public function getInstance() 
    { 
     if (!self::$_instance instanceof self) { 
      self::$_instance = new self(); 
     } 

     return self::$_instance; 
    } 
} 

如果你要封閉方法本身的變量,嚴格來說,它不會是一個類屬性。另外,你會失去一點可讀性,其他開發者(不習慣例B的設計模式)會尋找類屬性聲明,而不是通過類方法進行挖掘。

+0

感謝你的意見。我從可讀性的角度理解你的觀點,但似乎沒有任何技術上的觀點可以說明你的觀點。在旁註中,我沒有使用匈牙利符號,前綴與範圍不相關於變量類型。 – James

0

是否有類持有的靜態實例,並拿着它在返回實例的方法時,有什麼區別?

沒有,有在功能上沒有區別,授予你修改靜態實例屬性的知名度,保護或私有:

class cExampleA { 
    protected static $instance = null; 
    // ... 
} 

順便說一句,不要使用符號,如$mInstance;現在你不需要那些柺杖

另外,看到你如何設置構造函數爲受保護的可見性,我假設你想能夠在稍後擴展類?在這種情況下,你需要改變getInstance()方法:

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

否則,你的構造應該僅僅是私人,這樣就可以再次使用new self;

+0

我從未見過之前使用過的'新靜態'。通常,當我想擴展這個類時,我使用了不同的方法,這取決於實例將如何使用。在附註中,我經常收到關於我的編碼風格的評論。大多數人認爲這不是匈牙利符號,而是防止命名衝突的範圍指標。 – James

+0

@James yep這是遲到的靜態綁定:) –

相關問題