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

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


当前回答

延迟加载支持接口,以便提供单独的实现能够返回派生类型(作为lazyloading和接口实现的组合)

其他回答

从测试角度来看,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模拟静态,但并非所有产品都可以使用它。

静态类是一个只有静态方法的类,对于这个类,更好的词是“函数”。静态类中体现的设计风格纯粹是过程性的。

另一方面,Singleton是OO设计特有的模式。它是一个对象的实例(具有其中固有的所有可能性,例如多态性),具有一个创建过程,确保在整个生命周期中只有一个特定角色的实例。

当我想要具有完整功能的类时,例如,有很多方法和变量,我使用单例;

如果我希望类中只有一个或两个方法,例如MailService类,它只有一个方法SendMail(),我使用静态类和方法。

一个显著的区别是Singleton附带的不同实例化。

对于静态类,它由CLR创建,我们无法控制它。使用singleton,对象在尝试访问的第一个实例上实例化。

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

问题是错误的,这两种说法都是错误的。请注意:这里的静态类意味着嵌套的静态类,而不是只有静态方法的类。

我假设(即,静态类意味着嵌套的静态类,而不是只有静态成员的类),因为如果我看到最流行的Singleton实现,即DCL方式,它只不过是实例的静态声明和获取Singleton实例的静态方法。它是一个实现。那么在这种情况下,Singleton和只有静态成员的类之间有什么区别呢。尽管其他实现也是可能的,比如使用Enum。

让我纠正以下说法:

Singleton类可以具有单实例应用程序范围。嵌套的静态类可以有多个实例(请参阅下面的代码作为证明)。在这里阅读嵌套类的基础知识。没有一个类本质上是线程安全的,它必须通过编程实现线程安全。它既可以用于嵌套静态类,也可以用于Singleton。

下面是更多的神话故事(这个问题的大多数答案都给出了这些陈述,因此认为最好通过编程来证明这一点):

嵌套的静态类可以像任何其他类一样实现接口。嵌套的静态类可以扩展其他非最终类。嵌套静态类可以具有实例变量。嵌套静态类可以具有参数化构造函数。

在下面的代码中,您可以看到嵌套的静态类NestedStaticClass实现了接口,扩展了另一个类,具有实例变量和参数化构造函数。

 package com.demo.core;

    public class NestedStaticClassTest
    {
        public static void main(String[] args)
        {
            OuterClass.NestedStaticClass obj1 = new OuterClass.NestedStaticClass();
            OuterClass.NestedStaticClass obj2 = new OuterClass.NestedStaticClass();

            if(obj1 == obj2)
            {
                System.out.println("Both nested static objects are equal....");
            }
            else
            {
                System.out.println("NOT EQUAL......");
            }

            System.out.println(OuterClass.NestedStaticClass.d);

            obj1.setD(5);

            System.out.println(OuterClass.NestedStaticClass.d);

            System.out.println(obj1.sum());
        }
    }

    class OuterClass
    {
        int a =1;
        static int b = 2;

        static class NestedStaticClass extends OneClass implements Sample
        {
            int c = 3;
            static int d = 4;

            public NestedStaticClass()
            {
            }

            //Parameterized constructor
            public NestedStaticClass(int z)
            {
                c = z;
            }

            public int sum()
            {
                int sum = 0;
                sum = b + c + d + getE();
                return sum;
            }

            public static int staticSum()
            {
                int sum = 0;
                sum = b + d;
                return sum;
            }

            public int getC()
            {
                return c;
            }
            public void setC(int c)
            {
                this.c = c;
            }
            public static int getD()
            {
                return d;
            }
            public static void setD(int d)
            {
                NestedStaticClass.d = d;
            }
        }
    }

    interface Sample
    {

    }

    class OneClass
    {
        int e = 10;
        static int f = 11;

        public int getE()
        {
            return e;
        }
        public void setE(int e)
        {
            this.e = e;
        }
        public static int getF()
        {
            return f;
        }
        public static void setF(int f)
        {
            OneClass.f = f;
        }

    }