2012-07-13 62 views
2

假設您有一個與數據庫交互的系統。由於該系統採用數據庫如此嚴重,幾乎每個子程序遵循以下模式:Singleton或DRY

foo(database, rest, of, arguments) 

這注意到相當快,因爲​​foo是一個更大的目標的一部分,連接變量被移動到一個對象變量。不幸的是,這意味着每個模型對象的構造函數都需要這個參數。

因此您決定創建一個可以生成與數據庫連接的模塊。由於到數據庫的連接非常昂貴,因此連接會被緩存,並且將來的調用會返回緩存的值。

你剛剛創建的是一個單身人士。這是發展界普遍反對的一種模式。再次,DRY是一個鼓勵的原則,甚至比單身模式更受鼓勵。

那哪個更好?你的選擇是膨脹進入每個函數調用(或者至少是構造函數)的參數數量,或者創建一個單例。我沒有看到第三個選項嗎?

編輯:文章爭論單身人士是http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx。我認爲那裏提出的論點是有道理的,我希望反單體陣營能解決這個設計問題。

+0

如果你不能說出一個更好的理由不使用單例模式,而不是你不知道誰不參與你的開發過程而對它產生非特異性的憤怒聲音,我沒有看到爲什麼不使用它。設計模式分析的存在是爲了幫助你完成工作,而不是強制任意指出時尚性。 (並不是說你對DRY建議的原因有更具體的瞭解,但是它解決的問題是任何白癡可以看到的問題都不好。) – chaos 2012-07-13 19:40:44

+2

這裏的每個人都有一堆應該「永不」違反的「規則」,如果你將它們全部扔在一起,永遠不會寫出一行代碼。 – 2012-07-13 19:46:24

+0

夠公平的,我可以在我的理由更具體。我正在編輯帖子以包含每個人的原因鏈接。 – lackita 2012-07-13 19:47:17

回答

2

DRY是這樣,方式比「不使用單身」,如果有這樣的原理實際上是由沒有人關節更重要的(而不是,說,「不要濫用可怕單身」)。如果你願意,如果你願意,你可以隨意滿足,但是如果你只能滿足一個,那麼就滿足乾爽。

1

您可能還會考慮查找或注入模式。用連接細節創建一個單例,然後讓任何需要連接的類使用「查找」或創建一個系統將其注入到類中。如果濫用可能導致問題,但對於共享資源,這些方法對我來說很有意義。

+0

這個建議與我目前使用的非常接近。敘述是我如何抵達設計,然後有人說:「嘿,這是一個單身,不是那麼糟糕?」半小時的谷歌搜索和這個問題後面,我們在這裏。 – lackita 2012-07-13 19:57:56

+0

是的,在給定正確的上下文的情況下,依賴注入是避免在這種情況下使用單例的一種很好的方法。如果您有某種頂級App模型,那麼您可以將數據庫連接作爲屬性存儲在該模型上,而不是作爲類變量,現在大家都很開心。 – chaos 2012-07-13 20:01:32

+0

公平點,但你仍然需要傳遞應用模型,所以我們在同一條船上。 – lackita 2012-07-13 20:10:16

0

用作將全局變量引入系統的方式時,單身人士被認爲是不好的。

作爲static變量實施的單身人士是不好的,因爲他們不容易被嘲笑測試。作爲靜態的,它們不會被注入,這會隱藏依賴。您現在正在進行的討論是由於您在代碼中看到了這種依賴關係而提示的。太棒了!您正在聆聽代碼並嘗試尋找更好的設計。如果數據庫訪問是通過靜態入口點的話,您不會注意到依賴擴散。

使用一個類的單個共享實例(通常作爲服務)的幾個對象的概念是完全有效的設計。以這種方式思考,所有的服務對象最終都是一種'有限範圍的單身人士'。 I.E.在這個子系統中,只有一個X實例。正確實施這是一個佈線決策,而不是一個類實現決策。 I.E.你可以使用任何一個類作爲單例,只需要創建一個類並將同一個實例傳遞給任何需要它的類......所討論的類不知道它是單例。

我同意你把'數據庫'傳遞給很多對象是一種氣味。我會將所有對'數據庫'的調用都包含到強類型的Repository對象中,每個對象都有一個乾淨的接口,讓調用者可以請求它想要的數據集,而不必擔心如何將這些數據檢索或轉換爲域對象。然後,我將注入所需的存儲庫到以前使用數據庫的類的構造函數中,而不是在每次調用時傳遞它。如果你正在做'依賴注入',你會發現佈線代碼移出你的對象,進入工廠類。然後,這些工廠將只將注入庫注入到實際需要查詢存儲庫的類中。

我看到的一種模式是獲取它們並不真正需要的依賴的對象,因爲它們又將它傳遞到它們創建的其他對象上。這可以通過將這個「工廠」行爲分解爲它自己的類來防止。

無論如何..簡短的回答是「不斷挖掘......找出爲什麼這麼多類需要數據庫訪問,應用單一責任原則和依賴注入來限制擴散」。