2011-03-12 152 views
3

我有一些代碼,往往是這樣的:PHP OOP訪問方法的好習慣?

private $user; 

public function __construct() 
{ 
    $this->user = User::getInstance(); //singleton 
} 

public function methodOne() 
{ 
    return $this->user->foo(); 
} 

public function methodTwo() 
{ 
    return $this->user->foo2(); 
} 

public function methodThree() 
{ 
    return $this->user->foo3(); 
} 

我想如果我設置的用戶屬性爲實例,我可以在我的方法重新使用一個較短的名稱(以及在這種情況下,這並不是說要短得多)。我也認爲這樣做可能會節省一些資源(開始懷疑它),但是當我查看其他人的代碼時,我很少看到人們這樣做。他們通常只會打電話:

User::getInstance()->foo(); 
User::getInstance()->foo2(); 
User::getInstance()->foo3(); 

有沒有這種最佳實踐?也許如果它不是單身課程,你可以這樣做嗎?或者,也許你不應該這樣做?希望得到一些澄清,謝謝。

編輯: 櫃面有什麼誤會,我只是想知道如果我應該創建一個屬性實例存儲VS這個第一個例子:

public function methodOne() 
{ 
    return User::getInstance()->foo(); 
} 

public function methodTwo() 
{ 
    return User::getInstance()->foo2(); 
} 

public function methodThree() 
{ 
    return User::getInstance()->foo3(); 
} 

其實,現在我想想這可能少代碼,我不需要構造...

回答

2

確實有一些問題,你的方法。

  • 目前還不清楚你的類是否依賴於User類。您可以通過將用戶添加爲構造函數參數來解決此問題。
  • 單身漢往往是不好的做法。你的代碼演示了爲什麼:它是全局訪問的,因此很難跟蹤使用它的依賴關係(這指向了上述問題)。
  • 靜態方法經常被用作全局接入點(作爲對人們通常做User :: method()的迴應)。全球接入點與單身人士一樣存在相同的問題。他們也比較難測試。

我也沒有看到用新對象重複User對象的要點,除非你使用例如適配器模式。也許如果你能澄清這一點,我將能夠拿出一個比通用更好的替代:

class Foo { 
    public function __construct(User $user) { 
     $this->user = $user; 
    } 
    public function doXsimplified() { 
     $this->user->doXbutMoreComplex($arg1,$arg2, $arg20); 
    } 
} 
+0

+1中的「良好的操作規範」,對於很好的解釋 – 2011-03-13 00:35:11

+0

編輯我的文章,我也創建包裝,因爲它與另一個應用程序集成,所以我不必重命名所有我的方法,如果我以後更改應用程序我也不確定我是否能夠使用你展示的方法,因爲我沒有用戶對象呢? – Joker 2011-03-13 01:16:45

+0

@Joker這是一個很好的使用包裝。你的用戶對象在包裝對象出現的時候就開始起作用(因爲它在那裏是爲了操縱第三方用戶對象)。因此,如果您在創建用戶對象之前或之後創建其他用戶對象,則不會產生影響。 – koen 2011-03-13 14:30:02

2

我在PHP個人的偏好是使用類只對單身靜態方法,所以你必須

User::foo(); 
User::bar(); 
+0

+1,短而甜。 – 2011-03-12 23:37:05

+0

可以用'__callStatic' – mario 2011-03-12 23:47:43

2

我不會創建一個新類只是環繞這樣的單例。但是如果你的新課程增加了一些額外的邏輯,那麼你的例子就是合理的記住,如果你擔心你太冗長,你可以使用臨時變量來進行連續的函數調用。

$user = User::getInstance(); 
$user->foo(); 
$user->bar(); 

但個人而言,我不再使用單身人士。相反,我使用依賴注入。我喜歡sfServiceContainer,但也有其他的。有一個在這個系列文章:http://fabien.potencier.org/article/11/what-is-dependency-injection

UPDATE

根據補充意見,這是我會怎麼做:

class UserWrapper 
{ 
    private $user = null; 

    public function __construct($user) 
    { 
     $this->user = $user; 
    } 

    public function foo() 
    { 
     return $this->user->foo(); 
    } 

    ... 
} 

然後使用它是這樣的:

$user = new UserWrapper(User::getInstance()); 

爲什麼?所以如果我想測試UserWrapper類,我可以傳入一個僞造的User對象。 E.g:

class UserMock { ... } // A fake object that looks like a User 
$userTest = new UserWrapper(new UserMock()); 
+1

+1來實現,用於提及依賴注入。 – koen 2011-03-13 00:05:39

+0

是的,也會有一些額外的邏輯。這是一種與另一個應用程序集成,所以我包裝用戶類的方法,後來決定我改變應用程序,我不必重新命名一切。對於你顯示的代碼是的,我這樣做,但只是想知道什麼是最好的方法來使用,如果你只在每個方法中使用一次實例。編輯我的主要職位。 – Joker 2011-03-13 01:12:58

+0

如果你添加額外的邏輯,那麼你的代碼是好的。我唯一需要改變的不是在構造函數中獲取User的實例,而是將其作爲參數傳遞給構造函數(以方便依賴注入)。 – 2011-03-13 10:38:16

0

我通常是這樣的,如果你已經列入某種或配置文件的引導類。我通常會在引導程序中刪除$ user變量,這會在每次頁面加載時調用,然後將其作爲全局變量引用到其他php文件中,這就是我在引導程序文件中所要做的。

$user = new User(); 

那麼這就是我會在調用PHP文件

global $user; 
$user->foo(); 
+0

我相信使用全局變量不是php – 2011-03-13 00:34:26