2015-05-19 33 views
2

很多時候單身人士是一件壞事(例如參見herehere),我想避免它們。對於單身我沒有爲又一個替代性的一個典型應用情況是,當你有需要引用某種父/全局對象的多個對象。在頻繁參考的情況下替代單身人士

例子1:你有某種樹,每個樹葉對象必須知道根對象。 (這是不好的設計,但它只是一個例子)

例2:你通常喜歡global_config::get_instance()->get_item(name)

問題訪問的「全局」配置對象:針對給定的例子 - 有什麼替代方案概念單身從廣泛依賴通過開,並且每個實例儲存(又名Dependancy Injection)?

+0

保持簡單;使用單身人士。如果它確實適合你的情況,那麼使用它並不是一件壞事。避免過度使用它。 – andre

+0

對於第一個示例,您可能在葉中有一個成員變量,它是對根的引用,並在構建或更新樹時進行設置。就個人而言,我沒有看到更好的替代例子2替換單例。 – Brahim

回答

2

單身人士只能解決一兩件事:"static initialization order fiasco"其中全局對象在未確定的訂單實例,使他們能夠不依賴於對方。

否則,單身只是恰好就只存在只是一次全局可訪問的對象。

因此,對於容器,就像第一個例子中的樹,一個全球性的實例不是比單更糟。另外,配置(例2)大多是啓動時反序列化的設置容器,所以沒有什麼能阻止你將其設置爲普通的全局實例。

好一點的設計是全局組在「應用」類的應用程序,所以它至少是明確表示,他們是應用廣泛的對象和配置應該在啓動反正填寫。

更好的(更大的應用程序)是使應用程序出像大對象模塊,並從「應用」類傳遞需要「全局」,以他們有更清晰的依賴關係視圖。這些模塊還可以包含更大的對象,以接收對「全局變量」的引用,但只要知道如何訪問它們的模塊化全局變量,就不必訪問每個對象。

選擇更依賴注入方法的最後一個參數是您的對象將更容易對模塊進行測試,因爲您可以更容易地注入測試對象,並且所有帶狀態的全局變量都會干擾一系列測試。

1

我有時會發現有用的一種方法是允許get_instance()方法接收一些參數並根據此參數返回不同的對象,如下所示:global_config::get_instance(string serviceName)。如果你有幾個單例類,你可以使用相同的參數來獲得它們中的每一個,所以每個用戶只需要知道一個參數,而不是保持對所有單例的引用。

首先,所有對get_instance()的調用都可以返回同一個對象,而忽略參數,但是如果開發需要針對應用程序的不同部分使用不同的單例,則可以通過讓應用程序的不同部分通過與get_instance()不同的參數。

此外,這也將解決測試您的應用程序的問題,因爲您可以找到某種方法將特殊的模擬參數傳遞給get_instance()以接收模擬對象。

這可能對您的global_cofig示例有用,但對於您的樹示例,您應該明確地保留對葉子中根的引用。

+1

當你可以傳遞參數給#get_instance()返回不同的對象時,被稱爲Multiton模式http://en.wikipedia.org/wiki/Multiton_pattern – iluwatar

+0

@iluwatar,謝謝你的鏈接,不知道這個名字是什麼模式。 – Petr

1

問題:對於給定的實施例 - 在那裏單身從廣泛依賴通過開,並且每個實例儲存(又名Dependency Injection)任何替代概念?

在這兩種情況下,你在談論的信息知名度要求,不是單要求(即只有一個對象實例)。

Craig Larman's "Applying UML and Patterns"狀態有一個目的可以訪問一個對象四種方式:

  • 屬性能見度 - B是A的一個屬性

  • 參數可見度-B是A的方法參數。

  • 當地知名度 - B是A.

  • 全球知名度的方法(非參數)本地對象 - B在某種程度上是全局可見。

最後一個是Singleton提供的。這就是爲什麼這種模式有爭議。

依賴注入是第一個選項 - B在其構造函數中注入到A.

一般的經驗法則是:設計中暴露的信息越多,以後改變設計的難度就越大(因爲耦合和依賴該信息)。全局可見性使得在短期內輕鬆解決設計中的一些訪問問題。由於信息過度曝光,它有可能長期產生問題。