design-patterns - static單例 - synchronized singleton class




靜態類和單例模式之間的區別? (20)

  1. 單例對象存儲在堆中 ,但靜態對象存儲在堆棧中
  2. 我們可以克隆 (如果設計者不禁止它)單例對象,但是我們不能克隆靜態類對象。
  3. 單例類遵循OOP (面向對象原則),靜態類不遵守。
  4. 我們可以用Singleton類實現一個interface ,但是類的靜態方法(或者C# static class )不能。

靜態類和單例模式之間存在什麼真正的(即實際的)區別?

兩者都可以在沒有實例化的情況下被調用,它們都只提供一個“實例”,而且它們都不是線程安全的。 還有其他的區別嗎?


  1. 延遲加載
  2. 支持接口,以便可以提供單獨的實現
  3. 能夠返回派生類型(作為延遲加載和接口實現的組合)

Singleton模式比靜態類有幾個優點。 首先,單例可以擴展類並實現接口,而靜態類不能(它可以擴展類,但不會繼承它們的實例成員)。 單例可以初始化為懶惰或異步,而靜態類通常在初次加載時初始化,導致潛在的類加載器問題。 然而,最重要的優點是單身人士可以被多形地處理,而不會迫使他們的用戶假定只有一個實例。


Singleton的實例化,它只是一個實例化的實例,因此Singleton中只有一個實例。

一個靜態類不能被其他任何東西實例化。


靜態類: -

  1. 您不能創建靜態類的實例。

  2. 當加載包含類的程序或名稱空間時,由.NET Framework公共語言運行庫(CLR)自動加載。

  3. 靜態類不能有構造函數。

  4. 我們無法將靜態類傳遞給方法。

  5. 我們不能將靜態類繼承到C#中的另一個靜態類。

  6. 一個擁有所有靜態方法的類。

  7. 更好的性能(靜態方法在編譯時綁定)

辛格爾頓: -

  1. 您可以創建對象的一個實例並重用它。

  2. 當用戶請求時,第一次創建單例實例。

  3. Singleton類可以有構造函數。

  4. 您可以創建單例類的對象並將其傳遞給方法。

  5. Singleton類不會說任何繼承的限制。

  6. 我們可以處理單個類的對象,但不能處理靜態類的對象。

  7. 方法可以被覆蓋。

  8. 需要時可以延遲加載(靜態類總是加載)。

  9. 我們可以實現接口(靜態類不能實現接口)。


As I understand the difference between a Static class and non-Static Singleton class, the static is simply a non-instantiated "type" in C#, where the Singleton is a true "object". In other words, all the static members in a static class are assigned to the type but in the Singleton are housed under the object. But keep in mind, a static class still behaves like a reference type as its not a value type like a Struct.

That means when you create a Singleton, because the class itself isnt static but its member is, the advantage is the static member inside the Singleton that refers to itself is connected to an actual "object" rather than a hollow "type" of itself. That sort of clarifies now the difference between a Static and a Non-Static Singleton beyond its other features and memory usage, which is confusing for me.

Both use static members which are single copies of a member, but the Singleton wraps the referenced member around a true instantiated "object" who's address exists in addition to its static member. That object itself has properties wherein in can be passed around and referenced, adding value. The Static class is just a type so it doesn't exist except to point to its static members. That concept sort of cemented the purpose of the Singleton vs Static Class beyond the inheritance and other issues.


When I want class with full functionality, eg there are many methods and variables, I use singleton;

If I want class with only one or two methods in it, eg MailService class, which has only 1 method SendMail() I use static class and method.


一個。 序列化 - 靜態成員屬於該類,因此無法序列化。

灣 儘管我們已經將構造函數設置為私有,但靜態成員變量仍將被傳遞給子類。

C。 我們不能做懶惰的初始化,因為所有的東西都只會在類加載時加載。


一個靜態類只有靜態方法,對此,一個更好的詞將是“功能”。 體現在靜態類中的設計風格純粹是程序性的。

另一方面,Singleton是面向對象設計的特定模式。 它是一個對象的實例(具有內在的所有可能性,例如多態性),創建過程確保在整個生命週期中只有一個特定角色的實例。


單例的另一個優點是它可以很容易地被序列化,如果你需要將它的狀態保存到光盤或者將它發送到遠程的地方,這可能是必要的。


在單例模式中,您可以將單例創建為派生類型的實例,但不能使用靜態類來完成。

快速示例:

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer

在很多情況下,這兩者沒有實際區別,特別是如果單例實例永遠不會改變或緩慢變化,例如持有配置。

我認為最大的區別是單身仍然是一個普通的Java Bean,與專門的靜態Java類相反。 正因為如此,單身人士在更多情況下被接受。 它實際上是默認的Spring Framework的實例化策略。 消費者可能會或可能不知道它是一個單身人士,它只是把它當作普通的Java bean來對待。 如果需求發生變化,而單例需要成為原型,就像我們在Spring中經常看到的那樣,它可以完全無縫地完成,而不需要為消費者修改代碼。

其他人之前提到,靜態類應該是純粹的過程化的,比如java.lang.Math。 在我看來,這樣的一個類永遠不應該被傳遞,他們絕不應該把靜態final作為屬性。 對於其他任何事情,使用單例,因為它更加靈活和易於維護。


從客戶端的角度來看,客戶端已知靜態行為,但單身人士行為可以從客戶端隱藏完成。 客戶可能永遠不會知道他只有一次他一次又一次地玩弄。


從測試的角度來看,Singleton是更好的方法。 與靜態類不同,singleton可以實現接口,你可以使用模擬實例並註入它們。

在下面的例子中,我將說明這一點。 假設你有一個方法isGoodPrice(),它使用方法getPrice(),並且你實現getPrice()作為一個單例中的方法。

提供getPrice功能的單身人士:

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

使用getPrice:

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

最終的Singleton實現:

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

測試課:

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

如果我們採用靜態方法來實現getPrice()的替代方法,那麼模擬getPrice()就很困難。 你可以用動力模擬來嘲弄靜態,但並非所有的產品都可以使用它。


我們有我們的數據庫框架,可以連接到後端。為了避免多用戶的髒讀,我們使用單例模式來確保我們在任何時間點都有單一實例。

在c#中,一個靜態類不能實現一個接口。 當單個實例類需要實現用於業務契約或IoC目的的接口時,這就是我使用Singleton模式而沒有靜態類的地方

Singleton提供了一種在無狀態場景中維護狀態的方法

希望能幫到你..


我同意這個定義:

單一 ”一詞意味著整個應用程序生命週期中的單個對象,因此範圍在應用程序級別。

靜態沒有任何Object指針,因此範圍在App Domain級別。

而且兩者都應該被實現為線程安全的。

你可以找到有趣的其他區別: Singleton Pattern與Static Class


擴展Jon Skeet的答案

單例和一堆靜態方法之間的巨大差異是單例可以實現接口(或者從有用的基類派生,儘管這不是常見的IME),所以你可以將單例傳遞給它,就好像它是“另一個”實現一樣。

單元測試課程時單身人士更容易使用。 無論您將singleton作為參數傳遞(構造函數,設置函數還是方法),您都可以替換單例的模擬或存根版本。


是什麼讓你說單線程或靜態方法不是線程安全的? 通常兩者都應該被實現為線程安全的。

單身人士和一些靜態方法之間的巨大差異是單身人士可以實現接口(或者從有用的基類派生,儘管這在我的經驗中不太常見),所以你可以繞過單身人士,就好像它是“另一個“實施。


真正的答案是Jon Skeet, 在這裡的另一個論壇上

單例允許訪問單個創建的實例 - 該實例(或者對該實例的引用)可以作為參數傳遞給其他方法,並作為普通對象處理。

靜態類只允許靜態方法。


這裡有一篇很好的文章: http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html : http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

靜態類

  • 一個擁有所有靜態方法的類。
  • 更好的性能(靜態方法在編譯時綁定)
  • 不能覆蓋方法,但可以使用方法隱藏。 ( 什麼是隱藏在Java中的方法?即使JavaDoc的解釋也很混亂

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

獨生子

總之,我只會使用靜態類來保存util方法,並使用Singleton來完成其他任何事情。

編輯





singleton