2011-12-21 32 views
9

我不是單身人士的仇敵,但我知道他們受到虐待,因此我想學會避免在不需要時使用它們。需要幫助避免使用單身人士

我正在開發一個跨平臺的應用程序(Windows XP/Vista/7,Windows Mobile 6.x,Windows CE5,Windows CE6)。作爲該過程的一部分,我將代碼重新分解爲單獨的項目,以減少代碼重複,從而有機會解決初始系統的錯誤。

正在分離的應用程序中的一個這樣的部分非常簡單,它是一個配置文件管理器。這個項目負責存儲配置文件。它有一個Profile類,其中包含應用程序所有部分使用的一些配置數據。它有一個ProfileManager類,其中包含ProfilesProfileManager將在硬盤上讀取/保存Profiles作爲單獨的XML文件,並允許應用程序檢索並設置「活動」Profile。簡單。

在第一個內部構建中,GUI是反模式SmartGUI。這是一個沒有MVC/MVP的WinForms實現,因爲我們希望它能夠更快地工作,而不是很好的設計。這導致ProfileManager是一個單身人士。這在應用程序的任何地方都是如此,GUI可以訪問活動的Profile

這意味着我可以根據需要去ProfileManager.Instance.ActiveProfile檢索系統不同部分的配置。每個GUI還可以對配置文件進行更改,因此每個GUI都有一個保存按鈕,因此它們也都可以訪問ProfileManager.Instance.SaveActiveProfile()方法。

我在這裏看到使用單身人士沒有錯,並且因爲我沒有看到任何錯誤,但知道單身人士並不理想。 有沒有更好的方法來處理?應該將ProfileManager的實例傳遞給每個Controller/Presenter?當ProfileManager被創建時,是否應該創建其他核心組件並在配置文件發生更改時註冊到事件。這個例子非常簡單,可能是許多系統的一個共同特徵,所以認爲這是學習如何避免單身人士的好地方。

P.s.我不得不針對Compact Framework 3.5構建應用程序,這限制了很多可以使用的.Net Framework類。

+6

我可能會被困在我以前的習慣中,但我認爲這是應該使用Singleton的一個很好的例子。 –

+0

這實際上聽起來像是單身實例的理想情況。 – msarchet

+0

感謝所有的答案,它似乎是一個適合使用Singleton的地方。工廠/依賴注入的反饋將被考慮進來,但是由於這個應用程序將在後臺運行,我可能會將其作爲Singleton用於簡單性和性能。 – JonWillis

回答

8

單身人士受到誹謗的原因之一是他們經常充當全局,共享和有時可變狀態的容器。例如,當應用程序確實需要訪問全局共享狀態時,單身是一種很好的抽象:您需要訪問麥克風或音頻播放的移動應用程序需要協調此功能,因爲只有一組揚聲器。

對於您的應用程序,您有一個「活動」配置文件,應用程序的不同部分需要能夠修改。我認爲你需要決定用戶的個人資料是否真正適合這種抽象。鑑於配置文件的表現形式是磁盤上的單個XML文件,我認爲可以將它作爲單例使用。

不過,我認爲你應該使用依賴注入或工廠模式來獲取配置文件管理器。你只需要爲需要使用配置文件的類來編寫單元測試來理解這個需求;您希望能夠在運行時傳遞以編程方式創建的配置文件,否則您的代碼將與某個位於磁盤上的某個XML文件具有緊密耦合的依賴關係。

+0

部分重寫將被單元測試,而不是我的強點,但我會嘗試,仍然在學習TDD。尚未測試單身人士,但我認爲問題是與他們是實例(方法或屬性)是靜態的,因此不能輕易被模擬/存根靜態不能被覆蓋,這是如何模擬工作(在測試中添加生成的類的子類被模擬)。 – JonWillis

2

「單身人士」如果基本上被用來取代「全局」變量,那麼它們真的只是壞事。在這種情況下,如果這就是它的用途,那麼不一定是Singleton。

在你描述的情況下,它很好,而且實際上是理想的,這樣你的應用程序就可以確保配置文件管理器可供需要它的每個人使用,並且沒有其他應用程序可以實例化一個額外的配置文件將與現有的衝突。這樣可以減少每個地方的醜陋的額外參數/字段,試圖傳遞一個實例的地方,然後保留額外的不必要的引用。只要它被迫成爲一個且只有一個實例,我沒有看到任何錯誤。

Singleton旨在避免多個實例化和單個「入口」點。如果這就是你想要的,那麼這就是要走的路。只要確保它有充分的文件記錄。

+0

感謝您的輸入,我沒有「Singleton」和「單一參考」的擔憂,就像您聲明的那樣,在許多方法中都有額外的參數。這最終變成了一個混亂的業務。 – JonWillis

5

需要考慮的一件事是爲您的ProfileManager創建一個接口,並將其實例傳遞給使用它的每個視圖(或任何其他視圖)的構造函數。這樣,你可以很容易地擁有一個singleton,或者每個線程/用戶/ etc的一個實例,或者有一個實現轉到數據庫/ Web服務/等等。

另一種選擇是將所有使用ProfileManager調用的東西調用到工廠而不是直接訪問它。那麼這個工廠可能會返回一個實例,它可能是單身或不是(到數據庫或文件或Web服務等等),大部分代碼不需要知道。

不回答你的直接問題,但它確實使未來變化的影響接近於零。

+0

我確實考慮了一個接口,但知道只有一種類型的ProfileManager會因此而決定。使用工廠方法是另一個考慮,但我不願意提出它,因爲我覺得我正在添加代碼,無論如何返回單身人士,但我明白,如果實施更改,然後我只更新一個工廠的參考,而不是每一塊使用該單例的代碼。乾杯 – JonWillis