2015-04-07 26 views
5

我很掙扎,因爲這個:如何處理時間耦合?

我的類有一些方法有時間耦合。這是,一些方法方法A必須首先被調用以「初始化」方法B需要正常工作的數據。

我通常會令時空耦合明確通過將違規依賴於「方法b」作爲參數,就像這個片斷:

private class SomeClass 
{ 
    private string field; 
    private int count; 

    public SomeClass() 
    { 
     MethodA(); 
     MethodB(field); 
    } 

    private void MethodA() 
    { 
     field = "Something"; 
    } 

    private void MethodB(string str) 
    { 
     count = str.Length; 
    } 
} 

雖然這使事情變得明確,我覺得我做的有問題。我最終沒有使用字段的方法(靜態方法!),所以類開始看起來不那麼緊密。

這是最好的方法嗎? (通過傳遞參數失去凝聚力)

編輯:關於建議使用字段作爲參數或使用生成器模式來避免無效狀態的一些答案:我不能這樣做,因爲在我的情況下我正在構建一個解析器。 MethodA讀取輸入並根據它設置狀態(讀取文件中的字符),然後調用MethodB。必須按照正確的順序調用它們。這是真正的問題:一個應該在另一個之前被調用。

+0

你是否擔心你的私人方法的凝聚力,還是這是一個人爲的例子? – neontapir

+0

@neontapir:更高的凝聚力聽起來不像他應該擔心的事情。 –

+0

本文可能有所幫助:[方法調用之間的時間耦合](http://www.yegor256.com/2015/12/08/temporal-coupling-between-method-calls.html) – yegor256

回答

1

用戶可於MethodB刪除參數,並使用field,這樣你不會失去凝聚力

private class SomeClass 
{ 
    private string field; 
    private int count; 

    public SomeClass() 
    { 
     MethodA(); 
     MethodB(); 
    } 

    private void MethodA() 
    { 
     field = "Something"; 
    } 

    private void MethodB() 
    { 
     count = field.Length; 
    } 
} 

注:

1)您所描述的方式,這個問題似乎像模板方法設計模式,你應該have a look here

2)Static methods不屬於

+0

這在技術上是錯誤的。靜態方法只能屬於一個類。它們不屬於*實例*。 –

+0

你指的是什麼靜態方法,@ThorstenDittmar?所有這些對我來說都像實例方法。 – neontapir

+0

@ThorstenDittmar你說得對,靜態方法必須放在一個類中,但*不是那個類*。 – adricadar

0

我不知道你是什麼確切的目標,但爲什麼不把參數在類的構造函數:

private class SomeClass 
{ 
    private string _field; 
    private int _count; 

    public SomeClass(string field) 
    { 
     _field = field; 
     _count = field.Length; 
    } 

} 

現在你有這樣的事情

SomeClass sc = new SomeClass("Something");//or whatever you want for field. 
3

我想你需要有一種複雜的初始化,其中一些對在實際初始化對象之前必須指定儀表,並且希望更好地控制類用戶正在做什麼以避免無效狀態。解決這種情況的一個很好的知識模式是所謂的「Builder模式」,在OOP中很常用。我不想指出一篇特定的文章,您只需使用關鍵字「構建器模式」即可發現很多示例。爲了完整起見,總體思路是製作一系列方法指定內部字段的值,並委託一個最終方法「Build」來創建工作對象實例,並驗證傳遞的參數。

+0

好吧,我明白了你的觀點,但真正的問題是我構建了一個按順序讀取字符的解析器,因此MethodA從輸入讀取數據,將某些字段設置爲有效狀態並調用MethodB。你無法預測輸入。生成器對於某些情況非常有用,但是這種情況呢? – SuperJMN

+1

爲什麼你正在閱讀Parser類中的文件?我不明白,或者你的方法與SOLID原則相沖突? – mybirthname

3

流利的API的解決這種事情在公共接口通過不暴露在「建設者」對象依賴的方法,直到合適的:

SomeClass someInstance = SomeClassBuilder(x=> { 
    x.MethodA().MethodB("somevalue"); 
}); 

這需要很多更plumbling,因爲你所需要的建設者對象,以及構建器組件,例如從MethodA返回的公開MethodB的對象。這樣調用MethodB的唯一方法是首先調用MethodA。

我不鼓勵你採取這種方法。對於許多情況來說,這可能是矯枉過正的,但在遇到適合的場景時,瞭解此選項非常重要。

+0

我其實認爲這是解決這個問題的可行方法。 – neontapir

3

如果你關注貧血域模型,你可以打破你的課堂,讓它成爲2個小班。您意識到設計不好,因爲您當前的課程違反了SRP,總之它有2個責任:1個用於處理輸入過程,1個用於處理輸入結果。

將其分解,以便ClassA將處理輸入和返回結果,然後ClassB將從ClassA的結果作爲參數,然後對其進行處理。例如:

public class ClassA 
{ 
    public string MethodA() 
    { 
     // read the input 
     return "Something"; // or return the input 
    } 
} 

public class ClassB 
{ 
    private int count; 
    public void MethodB(string str) 
    { 
     count = str.Length; 
    } 
} 

如果您發現使用這兩個類是麻煩,使用另一個aggregate service了點。例如:

public class ClassC 
{ 
    public ClassA ClassA = new ClassA(); 
    public ClassB ClassB = new ClassB(); 
    public void Execute(){ 
     string result = ClassA.MethodA(); 
     ClassB.MethodB(result); 
    } 
} 
+0

完美的解決方案 – Mateusz