什麼時候單例實際上比靜態類更容易或更好?在我看來,創建一個單例只是額外的努力,但實際上並不需要,但我確信有一個很好的理由。否則,他們顯然不會被使用。爲什麼使用singleton而不是靜態類?
回答
寧願單身人士超過靜態類(假設你沒有更好的模式;))的一個好理由是將一個單例實例換成另一個。
舉例來說,如果我有一個日誌類是這樣的:
public static class Logger {
public static void Log(string s) { ... }
}
public class Client {
public void DoSomething() {
Logger.Log("DoSomething called");
}
}
它的作品真的很好,但如果記錄儀寫東西到數據庫,或將輸出寫入到控制檯。如果你正在編寫測試,你可能不需要所有這些副作用 - 但是由於日誌方法是靜態的,除了以外,你不能做任何事情。
好的,所以我想熱插拔我的Log方法進行測試。去小工具單身!
public class Logger {
private static Logger _instance;
public static Logger Instance
{
get
{
if (_instance == null)
_instance = new Logger();
return _instance;
}
set { _instance = value; }
}
protected Logger() { }
public virtual void Log(string s) { ... }
}
public class Client {
public void DoSomething() {
Logger.Instance.Log("DoSomething called");
}
}
所以,你可以定義一個空Log
方法TestLogger : Logger
,然後設置你的測試日誌的實例爲測試的單一實例。普雷斯托!您可以在不影響客戶端代碼的情況下對測試或生產的記錄器實現進行熱插拔。
單身通常優於全局變量,因爲:
- 他們不污染全局命名空間(或者在與命名空間,其含有的命名空間的語言)不必要的變數。
- 它們允許惰性分配和初始化,而許多語言中的全局變量總是會消耗資源。
編輯:
一種涼爽使用單例中,當與工廠方法相結合,可以用於創建Flyweight pattern。這是當你創建一個新對象時,Factory(而不是創建一個新對象)首先檢查是否已經創建了該對象的單例,如果是,它只是返回該對象,否則創建一個新的單例並返回它,跟蹤它創建的單例。 Flyweights由於單身人員的不變性而工作。
在許多語言中,靜態類缺乏有用的功能,如繼承(更普遍的是多態)。
單身保留傳統類的做法,不要求您使用static關鍵字隨處可見。起初他們可能要求更高,但會大大簡化程序的架構。與靜態類不同,我們可以使用單例作爲參數或對象。
此外,您可以像使用其他任何類一樣使用單例接口。
即使恕我直言,單例模式是一個相當濫用模式,但它有時會提供的好處,如:
- 使用不同類型的對象(即從相同的基本繼承)作爲實例的能力(例如,數據提供者使用文件系統,其中一個使用SQL數據庫)
- 可串行化。我沒有使用可以自動序列化靜態類的框架。
- 使用較少的靜態字段。對某些人來說,這更多的是審美特徵,但在某些情況下,它具有實際的好處。
單身對我來說似乎有點多餘。我更喜歡靜態類,如果我需要不同的行爲,我將它與依賴注入和提供者結合起來..我不知道這是什麼模式,或者它是否有名稱,但它通常是這樣的:
public interface IFooProvider {
Bar FooBar();
}
public static class Foo {
public static readonly IFooProvider FooProvider { get; set; }
public Bar FooBar() { return FooProvider.FooBar(); }
}
然後我只是確保在我的init方法中設置提供程序的某處。如果要通過在類初始化時設置默認提供程序來添加延遲初始化,這很容易。最重要的是,它可以讓你改變行爲,同時還能獲得使用靜態類的美感。
- 一個單可以實現接口,從其他類
- 一個singleton可以懶惰地或異步地進行初始化,並且由.NET Framework CLR(公共語言運行時)當包含類別的節目或命名空間是自動加載繼承加載。雖然靜態類通常在初次加載時初始化,並且會導致潛在的類加載器問題。
- 單例類遵循面向對象的原則
- 單個對象存儲在堆中,而靜態類存儲在堆棧中。
- Singleton對象可以有構造函數,而靜態類不能。
- 單一對象可配置而不是靜態類
- 單一對象可以複製,但不能用靜態類
- 1. 爲什麼文本在動畫中使用而不是靜態
- 2. 爲什麼使用靜態「常量」而不是實際值?
- 3. 爲什麼使用單例而不是靜態方法?
- 4. 爲什麼在StructureMap中處理Singleton類而瞬變不是
- 5. 爲什麼使用枚舉而不是帶有靜態常量的類?
- 6. 爲什麼AbstractFactoryUnit具有動態而不是靜態多態?
- 7. C#靜態類爲什麼使用?
- 8. 爲什麼要用path.join(),而不只是靜態的(「公共」)
- 9. 爲什麼不是方法引用singleton?
- 10. Singleton類,GraphicsManager和靜態
- 11. singleton類可以靜態嗎?
- 12. 爲什麼枚舉編譯爲常量而不是靜態值?
- 13. 爲什麼Grails服務類是Singleton?
- 14. 爲什麼說方法不是靜態時它是靜態的?
- 15. 靜態類不會先被調用,而會被實例類調用。爲什麼?
- 16. 爲什麼CanvasRenderingContext2D.createLinearGradient()不是靜態函數?
- 17. 爲什麼getAppProperty()不是靜態方法?
- 18. 爲什麼QDir :: rmdir不是靜態的?
- 19. 爲什麼Char.MinVal/.MaxVal不是靜態的?
- 20. 爲什麼接口變量總是靜態的,爲什麼不抽象類總是靜態的?
- 21. 爲什麼加載靜態html頁面而不是Wordpress?
- 22. 爲什麼不是Random類是靜態的?
- 23. 什麼是靜態庫,什麼是動態庫,有什麼區別,什麼是更好的使用,爲什麼?
- 24. 爲什麼要在靜態鎖定成員上而不是在類上同步?
- 25. 爲什麼公共靜態類的類
- 26. 爲什麼可以調用非靜態類的靜態方法?
- 27. C#何時使用靜態類而不是類的實例?
- 28. 爲什麼Singleton類可以作爲常規類使用
- 29. 爲什麼C#靜態類包含非靜態類/結構體?
- 30. 什麼是「靜態」?
飛錘更像是一個「多例」,不是一個真正的單身。 – BalusC 2010-06-03 20:51:45
Multiton ...我喜歡它! – 2010-06-03 20:53:03
它確實存在。參見[wikipedia](http://en.wikipedia.org/wiki/Multiton_pattern)。 – BalusC 2010-06-03 21:11:25