2013-07-26 115 views
3

我創建一個實用工具類CommonDaoOperations包含幾個通用的方法:CreateUpdateDelete。 這不是基類,因爲一些DAO更復雜,不能使用這些通用方法,但是很多DAO可以。實用工具類:靜態類VS成員變量VS局部變量

我現在琢磨的是utiliy類應該怎麼樣子正是:

  • 僅有靜態泛型方法
  • 普通班與通用方法,每個DAO創建一次私人只讀成員靜態類
  • 使用泛型方法的常規類,每個DAO方法創建一次(在每個調用中)

爲每個DAO /方法創建一個類的實例顯然花費了超過調用一個靜態方法,但我敢肯定,這些成本幾乎可以忽略任何應用程序。

我贊成,因爲非靜態類的好處的解決方案2或3(接口,可以嘲笑,可以得出/增強,可能在未來通過構造函數參數收集如果有必要(相比靜態類中的10參數方法))。

所以我想真正的問題是:我應該創建我的工具類作爲成員變量,或實例化它每個DAO方法?

public void Create(User user) { 
    new CommonDaoOperations().Create(user); 
} 
public void Delete(User user) { 
    var daoOps = new CommonDaoOperations(); 
    daoOps.CheckSomething(); // just an example of multiple calls to the class 
    daoOps.Delete(user); 
} 

我有興趣聽聽其他開發者去想任何這些方法,或者如果還是有問題再/更好的方式來做到這一點。

編輯

就意識到,我應該給的方法#3更多的思考 - 因爲瓦迪姆指出,更換時,它在每個方法的實例化的具體類會很麻煩,但我可以因素,在一個屬性:

private CommonDaoOperations DaoOps { 
    get { return new CommonDaoOperations(); } 
} 
public void Create(User user) { 
    DaoOps.Create(user); 
} 

我相信這是比上面的代碼片段更maintianable,但是知道我介紹了一個屬性在我的DAO一個「工具」類,這可能是本身就是一個代碼的氣味(如螞蟻p指向出)。

摘要

這是一個艱難的決定 - 而我接受了螞蟻P中的答案,瓦迪姆的回答也是合法的。使用哪種方法取決於效用類別所有3種方法都有其用途(更新後的#3除外)。至少這是我提供的答案。

  • 靜態類確實有其用途,但也有許多缺點如上面簡要提到的。
  • 常規類,按每個方法實例化: utiliy類創建並在需要的地方使用。減少依賴性,保持你的類型純粹。
  • 常規類,實例化爲成員:當許多/所有方法需要實用程序類的實例時,創建成員變量可能是一個更好的主意。這種方式更改類型或實例化方式變得更容易。
+0

你的'工具類'不應該是DAO的成員。 '靜態'看起來很好。 –

回答

2

我會讓那些對性能影響更有資格的評論;但是,這裏有我的想法在每個:

1.靜態類

這個概念是對簡單的,「uncomprehensive」的工具,不需要真正的可擴展性,但方法 - 如你注意自己 - 您共同DAO運營將會變得更加複雜。這不太可能作爲單個靜態類來管理,特別是當它用於多種不同類型的DAO時。

2.具體類,每個DAO實例化的對象

這是所有罰款和花花公子,但你真正需要的實用工具類是個人DAO中的一員?我能理解這一點,如果你需要的實用工具類中某種一致性和狀態持續性的,跨DAO的壽命,但似乎這些方法是相當模糊的(正如它的名字爲「工具」類)。

哪片葉子3.具體類,按每個方法實例化。這對我來說似乎是最自然的解決方案。這使您可以靈活地利用具體類的所有優點,如您在問題中所承認的那樣,同時將對象的範圍限制在需要的地方 - 單個方法調用。

您的班級應該演變成整個DAO所需的內容,例如:你突然需要維護對象的狀態(或者,如果你需要將其注入到DAO的構造函數,或沿着這些線路的別的東西),你可以隨時更改在那裏的實例化(雖然在我看來,如果出現這種情況,你不再有實用程序類,你需要重新考慮這個類如何適應你的架構)。

+0

感謝您的回答。既然你反對#2的建議,你對我的#3更新實施有什麼想法?它與成員解決方案有相同的缺點,但是Vadim有一個要點,當我必須替換實用程序類時,我必須搜索大量的實例。 – enzi

+0

每次使用它時都沒有真正意義的擁有一個屬性,並且只是在DAO中重新實例化類 - 如果你打算這樣做,那麼不妨將它保存爲一個成員變量。如果您預計必須這樣做,那麼必須在多個地方替換它的擔憂是有效的;然而,儘量減少你寫的每一堂課的情況,以防你最終想把它全部刪除,這對我來說似乎是一種反作用的方法。 –

+0

此外,由於你似乎正在看這個,我開始懷疑這應該是一個實用工具類而不是一個通用的存儲庫或類似的,其中**它管理你的DAO,而不是其他的方式。 –

2

除非您計劃創建這些對象的數量極多,否則我認爲它不會影響性能。

我寧願(2)。只需要爲每次使用創建它,那隻需編寫代碼即可。此外,如果你會永遠想使用某種形式的國際奧委會,獲得實用類作爲參數,改變它的初始化的方式或簡單地更改類到另一個類 - 具有單個成員改變比一個更容易改變它使用的所有地方。

除非你有一個很好的理由,否則遠離靜態或單身。 (一個非常好的理由的例子就像開發一個插件或者一個插件,其中你不能控制你的類被初始化和使用的方式)。

+0

感謝您的回答 - 我用不同的#3更新了我的問題,想法? – enzi

+0

1.每次創建類時都有什麼意義?爲什麼不創建一次並使用它?這個解決方案也沒有真正解決我提到的其他問題。2.我沒有解決設計問題,只是把你使用的公用設施看作是理所當然的。這確實是一種代碼異味(但有更糟糕的情況),但很難在不知道代碼的情況下說更具體的內容。 – Vadim

+0

@ 1:只有當我需要它時,對象才存在,而在構造函數中創建一個成員變量並存在,直到DAO被GCed,即使只有少數方法使用它(從DAO到DAO也不相同)。爲了清楚起見,爲什麼財產不能解決其他問題(IoC,改變其初始化的方式)?更改屬性的類型與變量或者初始化的方式應該對我的代碼有類似的含義。 – enzi

1

當考慮靜態類具體類肯定還有影響取於心,見例如可測試性(但不是那麼肯定是後出的話),但之間的區別和用法有首先重要的是,一些假設做:

  • 實例類有狀態,管理狀態和行爲都涉及到它的內部狀態,如果操作不以某種方式與內部狀態,這些都是真正的靜態方法的候選人,但我會更多地說關於這一點。這是即使封裝基礎上,並用手去手SRP(單一職責原則),它說,一個類應該有一個責任,做一兩件事,並沒有更多的,因此,這給你一個事實,即方法都涉及到它的內部狀態直接或間接

    沒有,不管理國家
  • 靜態類。也許有人可能會說這不是真的,看單身。好吧,單身人士也許很好,但是設計爲靜態類的單身人士與反模式太接近了,在這種情況下,單身人士可以像IoC容器一樣管理,只需管理一個實例即可。如果需要,我可以提供一些有關容器和不用容器的例子。

好,有人說靜態類是一些接近反模式,因爲例如可測性..好,這是真正的無,這取決於什麼樣的靜態類和測試涉及到有關。 我會舉一個非常好的例子,由偉大的軟件架構師的所有,Udi Dahan,例如,在一篇關於域名事件的好文章中,他談到了其他事情,關於靜態類和可測試性,這裏的鏈接Domain Events Salvation如果你去的部分如何提高域事件,他談到了該領域的事件單元測試。

之後,你說,關於兩個另一個不同之處,是有關內存成本,但也有人說這一點。請記住,像Reshaper這樣的工具會提出建議,將不處理狀態的實例類/方法轉換爲靜態表示形式,這有利於內存和使用。

你設計的最後一句話:CommonDaoOperations似乎一個真正的靜態類,它不處理的狀態,所以這是一個很好的候選人是一個靜態類,爲它的性質,它的工作。您可以改爲使用IoC容器將其視爲「單例」,並以正確的方式配置該類。有許多方法可以在沒有容器的情況下以其他方式實現這個功能..這裏有一個簡單的文章,講述單身人士和靜態類C# Singleton, Static Class。當然,使一個返回幫助者的財產並不是一個好設計,並且返回一個get操作的新實例的財產總是一個糟糕的設計,它將以合理的理由被證明是合理的...

所以看到你的設計以及你如何使用助手類,Udi在上面的鏈接中說的話很好地描述了你應該實現的解決方案。

+0

靜態類肯定有它們的用途,但我認爲任何無狀態的類都應該是靜態的。以「IEqualityComparer」爲例。雖然您可以創建一個用於比較對象的靜態類(畢竟不需要任何狀態),但常規的類/接口方法非常強大且靈活。你提供的域名事件鏈接包含一個合法的靜態類的例子,但是這不應該被用作使每個無狀態類都成爲靜態的藉口(就像該站點上的處理程序類型一樣)。 – enzi

+0

我完全同意你的意見,其實我說的是一般性解釋。就個人而言,我不喜歡很多靜態類。在真正需要和合理的時候,應該仔細使用它們!乾杯 – Hoghweed