静态类和单例模式之间存在什么实际的区别?

两者都可以在没有实例化的情况下调用,两者都只提供一个“实例”,而且都不是线程安全的。还有其他区别吗?


当前回答

与静态类相比,Singleton模式有几个优点。首先,单例可以扩展类和实现接口,而静态类不能(它可以扩展类,但不继承它们的实例成员)。单例可以延迟或异步初始化,而静态类通常在首次加载时初始化,这会导致潜在的类加载器问题。然而,最重要的优点是,可以在不强迫用户假设只有一个实例的情况下以多态的方式处理单态。

其他回答

单例只是一个被实例化的普通类,但仅从客户端代码间接实例化一次。静态类未实例化。据我所知,静态方法(静态类必须有静态方法)比非静态方法更快。

编辑:FxCop性能规则描述:“不访问实例数据或调用实例方法的方法可以标记为静态(在VB中共享)在这样做之后,编译器将向这些成员发出非虚拟调用点,这将防止在运行时对确保当前对象指针为非空的每个调用进行检查。这可以为性能敏感的代码带来可衡量的性能增益。在某些情况下,无法访问当前对象实例表示正确性问题。"我不知道这是否也适用于静态类中的静态方法。

Singleton的被实例化。只是只有一个实例被创建过,因此在Singleton中只有一个。

另一方面,静态类无法实例化。

静态类示例

public class Any {

    private static Any instance = new Any();

    private Singleton() {
        System.out.println("creating");
    }
}

单例模式只存在一个实例:

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
        System.out.println("creating");
        if (instance != null) {
            throw new RuntimeException("Imposible create a new instance ");
        }
    }
}

从测试角度来看,Singleton是更好的方法。与静态类不同,singleton可以实现接口,您可以使用mock实例并注入它们。

在下面的示例中,我将对此进行说明。假设您有一个使用getPrice()方法的方法isGoodPrice(。

提供getPrice功能的singleton:

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)。您可以使用power mock模拟静态,但并非所有产品都可以使用它。

我将努力超越WTMI和WTL;DR响应。

单身者是一个物体的实例。。。句点

你的问题基本上是问类和该类的实例之间的区别。我认为这很清楚,不需要详细说明。

singleton的类通常采取步骤来确保构建一个实例;这很聪明,但不是必须的。

示例:var connection=connection.Instance;

假设这是Connection类:

public sealed class Connection 
{
    static readonly Connection _instance = new Connection();

    private Connection() 
    {
    }

    public static Connection Instance
    {
        get
        {
           return _instance;
        }
    } 
}

请注意,您可以在该类上抛出一个接口并模拟它以进行测试,这是静态类无法轻易做到的。