2010-02-03 49 views
6

舉例說明什麼是這個問題:何處放置多個類使用的方法?

我目前在我正在研究的PHP項目中的一個兩難。我想到了一個將被多個類使用的方法(本例中爲UI - MVC模型),但我不確定如何在面向對象設計中表示這樣的方法。我想到的第一件事是創建一個靜態函數的類,當我需要它時,我會打電話。不過,我不確定這是否正確。

更確切地說,我想要隨時工作。所以我需要幾種處理時間的方法。我正在考慮創建一個Time類,其中我會檢查時間是否是正確的格式等功能

有些人可能會說,我不應該使用類,因爲在PHP中,我仍然可以使用程序代碼。但我更感興趣的是回答,這將啓發我如何在OOP/OOD中處理這種情況。

所以實際的問題是:如何表示這樣的方法?靜態函數的方法是否足夠好,還是我應該重新考慮其他任何東西?

+0

如果類通過IS_A關係關聯,則只應使用繼承方法。否則使用一個模塊。 – 2010-02-10 13:15:58

回答

5

我會建議創建一個普通類包含此行爲,然後讓該類實現從類的成員中提取的接口。

無論何時您需要調用這些方法,都會將接口(不是具體的類)注入到消費者中。這可以讓你改變兩個彼此獨立。

這可能聽起來像更多的工作,但只是應用了Strategy設計模式。

這也會使單元測試代碼更容易,因爲代碼更鬆耦合。


下面是C#中的示例。

接口:

public interface ITimeMachine 
{ 
    IStopwatch CreateStopwatch(); 

    DateTimeOffset GetNow(); 
} 

生產實施:

public class RealTimeMachine : ITimeMachine 
{ 
    #region ITimeMachine Members 

    public IStopwatch CreateStopwatch() 
    { 
     return new StopwatchAdapter(); 
    } 

    public DateTimeOffset GetNow() 
    { 
     return DateTimeOffset.Now; 
    } 

    #endregion 
} 

和這裏的接口的消費者:

public abstract class PerformanceRecordingSession : IDisposable 
{ 
    private readonly IStopwatch watch; 

    protected PerformanceRecordingSession(ITimeMachine timeMachine) 
    { 
     if (timeMachine == null) 
     { 
      throw new ArgumentNullException("timeMachine"); 
     }   

     this.watch = timeMachine.CreateStopwatch(); 
     this.watch.Start(); 
    } 

    public abstract void Record(long elapsedTicks); 

    public virtual void StopRecording() 
    { 
     this.watch.Stop(); 
     this.Record(this.watch.ElapsedTicks); 
    } 
} 
+0

這意味着我應該創建類來處理這些函數中的每個函數的自定義函數+類,然後只需調用execute()?因此,例如,函數「timeToString」將成爲一個單獨的類,只有execute()函數,實現接口。我會通過新的CustomFunction(新的TimeToString)來調用它; ... $ custom_function-> execute()?戰略模式是如何工作的,還是我誤解了這個概念?爲每一個功能創建基本類是不是有點矯枉過正? – 2010-02-03 12:58:12

+0

您不必爲每個功能創建一個類。您可以將相關操作捆綁到一個類中。畢竟這就是封裝和粘合的全部內容。這些操作都可以在同一個接口上定義,從而使您能夠在一個捆綁中傳遞一組緊密集合的操作。 – 2010-02-03 13:33:22

+0

請問您可以用一個簡短的例子(用任何語言)編輯您的文章?由於我仍然不明白如何做到這一點。我應該簡單地創建一個具有多個函數的類,實現一個從成員中提取的接口,然後在需要的地方插入這個接口並通過它調用所有這些函數?我認爲讓我困惑的是你提到了戰略模式,我試圖完全按照它來實施解決方案。我也不明白爲什麼我會有一個只有一個類實現的接口。通過調用具體課程來防止緊密耦合? – 2010-02-04 14:34:53

0

使用一個類作爲命名空間。所以是的,有一個靜態類。

class Time { 
    public static function getCurrentTime() { 
     return time() + 42; 
    } 
} 
+3

靜態等級=緊密耦合 – 2010-02-03 10:16:02

+0

@Seemann,我更喜歡簡單的「正確」和「正確」的解決方案(是的,有時我有點虛僞)。如果我以後需要創建一個「普通」類,那麼我可以輕鬆地重構代碼來完成此操作。否則,浪費時間,國際海事組織。 – strager 2010-02-03 10:21:34

0

我不做PHP,但從OO的角度來看,將這些實用方法作爲靜態方法放置很好。如果它們是完全可重用的,請考慮將它們放在utils類中。

+1

靜態類別=緊密耦合 – 2010-02-03 10:16:31

+0

並非我不欣賞IoC/dep inj,但在這種情況下,如果某個方法處理的是直接且不可擴展的某個方法,那麼創建另一個間接方向似乎是過度工程。 – spender 2010-02-03 10:20:40

+2

時間既不是直接也不是不可擴展的。在單元測試中,通常非常重要的一點是,您可以模擬「當前」時間在彼此的毫秒內具有許多不同的值。 – 2010-02-03 10:22:59

1

雖然你說你要對任意的,無關的功能的結構,你已經給出了一個Time類的例子,它有許多相關的功能。因此,從OO的角度來看,您將創建一個Time類並具有一個靜態函數getCurrentTime(),例如,它將返回此類的一個實例。或者你可以定義構造器的默認行爲是返回當前時間,無論你喜歡什麼。或兩者。

class DateTime { 

    public static function getNow() { 
     return new self(); 
    } 

    public function __construct() { 
     $this->setDateTime('now'); 
    } 

    public function setDateTime($value) { 
     #... 
    } 

} 

但除此之外,已經有一個builtin DateTime class in PHP