我们什么时候应该在 Java 中使用 Singleton 类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7207861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:04:39  来源:igfitidea点击:

When we should go for a Singleton class in Java?

javasingleton

提问by M Sach

As per my thoughts, we should make a class as Singleton when we share the same object state across the application. In that case we want the user to to restrict from creating a new instance every time so that they could not maintain the multiple states. Agreed. But the same behavior can be acheved by by declaring the instance variables as static. To me it looks it will also serve the same purpose whether its cacheobjectcontainer, loggeror Classloaderclass.

按照我的想法,当我们在整个应用程序中共享相同的对象状态时,我们应该将一个类设为 Singleton。在这种情况下,我们希望用户限制每次创建新实例,以便他们无法维护多个状态。同意。但是可以通过将实例变量声明为静态来实现相同的行为。对我来说,它看起来也将用于相同的目的,无论是它的cacheobjectcontainer,logger还是Classloader类。

Please help me to understand above concept where static instance variable will not solve the purpose and class needs to be declared Singleton?

请帮我理解上面的概念,静态实例变量不能解决目的,类需要声明为单例?

Edited Part

编辑部分

Ok let me bring some more clarity . The pupose of singleton class is to keep only one instance of singleton class across jvm. Agreed. But i am trying to think of reasons why we want to keep only one instance. There can be two reasons:

好的,让我更清楚一些。单例类的目的是在 jvm 中只保留一个单例类的实例。同意。但我正在考虑为什么我们只想保留一个实例。可能有两个原因:

1) Object might be expensive to create. So we just want to keep only one instance. Agreed in this scenario declaring instance variables as static does not solve any purpose.

1) 创建对象可能很昂贵。所以我们只想保留一个实例。在这种情况下同意将实例变量声明为静态并不能解决任何目的。

2) We want to share the same state of object across application. I was thinking this is the main purpose of declaring the class as singleton. But it can be achieved simply by declaring the instance variables as static.

2)我们希望跨应用程序共享相同的对象状态。我认为这是将类声明为单例的主要目的。但是它可以通过将实例变量声明为静态来实现。

But looks like 1 is the main reason of delaring any class as static not reason 2 because it can be achieved with static variable also.

但看起来 1 是将任何类声明为静态而不是原因 2 的主要原因,因为它也可以用静态变量来实现。

Is this correct?

这个对吗?

回答by Amir Raminfar

Declaring the instance variable makes that reference a static object. Meaning there is only one instance of it for thatclass. But it doesn't stop anybody else from doing new SomeObject()regardless of if it is static reference. The idea of having a singleton class is to control the instances. For example, if you make the constructor private, you cannot do a newto create a new instance. Hence, you are controlling the creation of the instances.

声明实例变量使该引用成为静态对象。这意味着该类只有一个实例。但是,new SomeObject()无论它是否是静态引用,它都不会阻止其他任何人这样做。拥有一个单例类的想法是控制实例。例如,如果您创建了 constructor private,则不能执行 anew来创建新实例。因此,您正在控制实例的创建。

回答by Matteo

the main difference is that a singleton is a normal instance that you can for example use as a parameter. Singletons can also implement interfaces.

主要区别在于单例是一个普通实例,您可以将其用作参数。单例也可以实现接口。

Matteo

马泰奥

回答by StriplingWarrior

If you ever think you might want to leverage inheritance or interfaces, you'll want to use an actual instance rather than a static class. For example, what if you want to set up your instance to do something slightly different than it would normally do? You could set the singleton value to an instance of a different implementation of the interface, or to a child class that overrides certain functionality. All the code that accesses that singleton instance can use it in exactly the same way, but its behavior can be changed.

如果您认为您可能想要利用继承或接口,您将想要使用实际实例而不是静态类。例如,如果您想将实例设置为执行与通常情况略有不同的操作,该怎么办?您可以将单例值设置为接口不同实现的实例,或者设置为覆盖某些功能的子类。所有访问该单例实例的代码都可以以完全相同的方式使用它,但它的行为是可以改变的。

I would add, though, that both Singletons and static classes are considered an anti-pattern these days. Better to use dependency injection, and just use a singleton binding if you want singleton behavior.

不过,我要补充一点,现在单例类和静态类都被认为是反模式。最好使用依赖注入,如果你想要单例行为,就使用单例绑定。

public class SessionManager {
    private static final SessionManager instance;
    static {
        instance = SystemConfig.isDebug() ? new DebugSessionManager() : new SessionManager();
    }

    public static SessionManager getInstance() {
        return instance;
    }


    public int getActivePersonId() {
         // default implementation
    }
}

public class DebugSessionManager : SessionManager {
    @Override
    public int getActivePersonId() {
         // debug implementation
    }
}

// The code can be used in the same way regardless of whether we're in debug mode:
int personId = SessionManager.getInstance().getActivePersonId();

Update

更新

After reading the question again, it sounds like you're thinking of doing something like this:

再次阅读问题后,听起来您正在考虑做这样的事情:

public class SessionManager {
    private static String systemName;
    public String getSystemName() {return systemName;}
}

... the assumption being that systemNamewill never change, and so it doesn't matter if it is accessed as new SessionManager().getSystemName()versus SessionManager.getInstance().getSystemName(). In that case:

... 假设systemName永远不会改变,所以如果它作为new SessionManager().getSystemName()vs访问并不重要SessionManager.getInstance().getSystemName()。在这种情况下:

  1. From a semantic standpoint, when another programmer sees new SessionManager(), they are expecting that something newis being created. It is not immediately obvious that every SessionManagerin the system is always going to produce the same systemName. So a singleton may be preferable simply to make it more obvious to consumers that they will be dealing with a singleton state.
  2. There is a very slight overhead when you create the new SessionManager(), which must later be garbage-collected.
  1. 从语义的角度来看,当另一个程序员看到 时new SessionManager(),他们期望new正在创建某些东西。SessionManager系统中的每个人总是会产生相同的systemName. 因此,单例可能更可取,只是为了让消费者更清楚他们将处理单例状态。
  2. 创建 时有一个非常小的开销new SessionManager(),稍后必须对其进行垃圾收集。

Other than that, you'll basically have the same advantages and drawbacks with this approach as if you used a Singleton. I'll reiterate my earlier statement, though: Singletons are an anti-pattern. Prefer dependency injection.

除此之外,使用这种方法的优缺点基本上与使用 Singleton 相同。不过,我将重申我之前的声明:单例是一种反模式。首选依赖注入。

回答by rajah9

Several good answers so far.

到目前为止有几个很好的答案。

This When is a Singleton not a Singletonarticle expresses the concept well.

This When is a Singleton not a Singleton文章很好地表达了这个概念。

Here are some additional differences:

以下是一些额外的差异:

  • Singletons can be stateful, but static variables cannot.
  • Singleton classes may be subclassed
  • 单例可以是有状态的,但静态变量不能。
  • 单例类可以被子类化

回答by codingclues

Firstly You to check your object can have muliple states(like for human states are reading,singing) or not. Then you can decide to go for Singleton Object.

首先你要检查你的对象是否可以有多种状态(比如人类的状态是阅读、唱歌)。然后你可以决定选择单例对象。

Singleton provide great way to control memory footprint. In jdk Runtime class is singleton. Through Runtime.getRuntime()we get the object. Why do there need mutiple Runtime Objects. Only with One Runtime. process can be executed.

单例提供了很好的方法来控制内存占用。在 jdk 运行时类是单例。通过Runtime.getRuntime()我们得到对象。为什么需要多个运行时对象。只有一个运行时。进程可以执行。