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

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


当前回答

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

其他回答

a.序列化-静态成员属于类,因此无法序列化。

虽然我们已经将构造函数私有化,但静态成员变量仍将被携带到子类中。

c.我们不能进行延迟初始化,因为只有在类加载时才会加载所有内容。

在单例模式中,可以将单例创建为派生类型的实例,但不能使用静态类。

快速示例:

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

我头脑中的不同是实现面向对象编程(Singleton/Prototype)或函数编程(Static)。

我们过于关注单例模式创建的对象数量,而我们应该关注的是最终我们持有一个对象。正如其他人已经说过的,它可以扩展,作为参数传递,但最重要的是它是状态满的。

另一方面,静态用于实现函数式编程。静态成员属于一个类。他们是无国籍的。

顺便问一下,您是否知道可以创建单例静态类:)

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

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

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