2011-03-02 106 views
14

與同事討論過這是否是不好的做法。現在我無法找到這個在線的直接例子。靜態方法get - 這是不好的做法嗎?

我們有很多的數據庫對象映射器和調用它的功能,像這樣

(例如) - 該SETID方法得到的從數據庫中讀取行,並設置它的預定義propertys

class Person { 

    public static function get($id) { 
     $object = new Person; 
     $object->setId($id); 
     return $object; 
    } 
} 

使用它這樣我們可以用簡單的結構是這樣的:(這裏我們得到了從-例如後的ID)

$person = Person::get($id); 

,而不是

$person = new Person; 
$person->setId($id); 

現在,我的直覺告訴我,這是不好的做法。但我無法解釋它。也許這裏有人能解釋這是爲什麼,或者是不壞的做法

下面是我們如何使用它的一些其他的例子。我們主要將它用於獲得者。 (只是名稱,而不是代碼,幾乎所有的人都只是運行一個查詢,它可以返回1個對象,然後使用結果的ID使用SETID法)

class CatalogArticle { 
    public static function get($id) { } 
    public static function getByArticlenumber($articlenumber) {} //$articlenumber is unique in the database 
    public static function getRandom() {} //Runs a query returning a random row 
} 
+0

*(相關)* http://stackoverflow.com/questions/5166087/php-global-in-functions/5166527#5166527 – Gordon 2011-03-02 12:53:15

+0

只是我的兩分錢,但Laravel的泰勒Otwell了熱因爲他使用工廠模式的靜態方法和其他靜態方法,但猜猜什麼是100%的單位覆蓋率。 – 2014-01-02 06:46:47

回答

12

這不是可怕 PerSay公司。這是一個Factory Method設計模式的實現。原則上這並不差。

但是,在您的具體示例中,它並沒有真正做出任何重要的事情,所以我不太確定是否有必要。您可以通過爲id的構造函數提供(也許是可選的)參數來消除需求。然後任何人都可以撥打$foo = new Person($id);而不需要一個明確的工廠。

但是,如果實例化非常複雜,或者您希望能夠構建幾種只能由邏輯確定的不同人員類型,則工廠方法可能會更好。例如,假設您需要確定通過某個參數實例化的人員的類型。然後,工廠方法Person將是適當的。該方法將確定要加載的「類型」,然後實例化該類。

靜態一般很難測試,並且不允許像實例那樣的多態變化。他們還在代碼中的類之間創建了很強的依賴關係。他們不是可怕的,但如果你想使用它,你應該真的考慮它。一個選項是使用BuilderAbstract Factory。這樣,你創建了一個builder/factory的實例,然後讓這個實例決定如何實例化最終的類...

另外一個註釋。我會將該方法從Person::get()重命名爲更適合某種語義的內容。也許Person::getInstance()或其他合適的東西。

5

本博客文章應該告訴你爲什麼人們不喜歡靜態方法比我能更好地:

http://kore-nordmann.de/blog/0103_static_considered_harmful.html

是我印象最深有關當前的代碼段的問題:是一個人允許沒有ID?

我覺得,如果它代表一個真實的人應該是一個構造函數參數。如果你使用這個類來創建新的人,那可能無法工作。


2次調用之間的差異較小。這兩個「創建」一個人類,並設置ID,所以當你遇到'硬連線依賴'時,你不會贏得/放棄任何東西。當你希望能夠到一個人傳遞到另一個對象

優勢只顯示和對象需要更改ID(作爲一個例子,博客文章應該解釋,比我在這裏做)。

2

我只是添加到edorian的帖子,但我過去使用過靜態獲取方法,在那裏有一個緩存引擎,並且(例如)我可能在memcache中有一個給定的Person對象,並且寧願從緩存中檢索它,而不是去數據庫。

例如:

class Person { 

    public static function get($id) { 

     if(Cache::contains("Person", $id)) 
     { 
      return Cache::get("Person", $id); 
     } 
     else 
     {   
      //fictional get_person_from_database, basically 
      //getting an instance of Person from a database 
      $object = get_person_from_database($id); 
     } 
     return $object; 
    } 

} 

這樣一來,所有的緩存處理是有問題的類,而不是調用者得到一個人的電話不必擔心緩存來完成。

1

長話短說,是的,他們是不好的做法:

一個很好的理由除了一切的就是你 '應該' 是測試你的代碼。靜態方法造成的問題,所以你有一個很好的理由:

    如果你想跟隨的良好做法,測試你的代碼
  • 人機工程學,如果靜態的原因測試問題,靜電防止寫作測試,以便它可以防止跟隨良好做法:-)