当前位置: 首页 > 面试题库 >

为什么会有Java单例类?您什么时候需要使用一个

毛景曜
2023-03-14
问题内容

我知道单例类是只能有一个实例化的类,但是我不明白为什么这样做会有用。为什么不只创建带有静态变量和方法的类,并在需要时使用sync来确保没有两个线程同时执行该类中的方法。我只是不明白为什么有人会遇到创建此类课程的麻烦。我知道我在这里想念什么。

谢谢,


问题答案:

当我同意其他答案时,OP询问为什么不使用具有所有静态方法的类(可能具有静态字段),而不是拥有一个实例的单例。

为什么使用单身人士?

您可以通过Google“单身人士”找到各种原因。从JavaWorld:

有时候,只需要一个类的实例是合适的:窗口管理器,打印后台处理程序和文件系统是典型的示例。通常,那些类型的对象(称为单例对象)可以被整个软件系统中的不同对象访问,因此需要全局访问点。当然,只要您确定自己永远不需要一个以上的实例,那么您便会改变主意。

为什么要使用Singleton而不是所有静态方法的类?

几个原因

  1. 您可以使用继承
  2. 您可以使用界面
  3. 它使对单例类本身的单元测试变得更容易
  4. 这样就可以对依赖于单例的代码进行单元测试

对于#3,如果您的Singleton是一个数据库连接池,则要确保您的应用程序只有一个实例,但是要对数据库连接池本身进行单元测试,而不会影响数据库(可能使用package-
scope构造函数或static创建方法):

public class DatabaseConnectionPool {
  private static class SingletonHolder {
    public static DatabaseConnectionPool instance = new DatabaseConnectionPool(
        new MySqlStatementSupplier());
  }

  private final Supplier<Statement> statementSupplier;

  private DatabaseConnectionPool(Supplier<Statement> statementSupplier) {
    this.statementSupplier = statementSupplier;
  }

  /* Visibile for testing */
  static DatabaseConnectionPool createInstanceForTest(Supplier<Statement> s) {
    return new DatabaseConnectionPool(s);
  }

  public static DatabaseConnectionPool getInstance() {
    return SingletonHolder.instance;
  }

  // more code here
}

(注意使用Initialization on Demand
Holder
模式

然后,您可以DatabaseConnectionPool使用package-scope createInstanceForTest方法对进行测试。

但是请注意,使用静态getInstance()方法会导致“静态粘连”,其中依赖您单例的代码无法进行单元测试。
因此,通常不认为静态单例是一个好习惯
(请参阅此博客文章)

相反,您可以使用像Spring或Guice这样的依赖注入框架来确保您的类在生产中只有一个实例,同时仍然允许使用该类的代码可测试。由于Singleton中的方法不是静态的,因此可以使用JMock这样的模拟框架在测试中模拟您的Singleton。



 类似资料:
  • 问题内容: 我对JAX-WS进行了概述,并注意到了(和)的一些引用。 在什么情况下需要?(我认为JSR 109服务器?!) 问题答案: 是使用SUN的参考实现将Web服务作为标准存档部署在非Java EE5 Servlet容器上时所需的专有部署描述符。 Sun的RI 用作servlet上下文事件的侦听器和调度程序servlet。两者都必须在中声明。然后需要该文件为定义Web服务端点,以使其知道必须

  • 问题内容: 我如何使用AtomicBoolean?该类的作用是什么? 问题答案: 当有多个线程需要检查并更改布尔值时。例如: 这不是线程安全的。您可以使用以下方法修复它:

  • 问题内容: 当我尝试按照本指南进行SQLAlchemy Relation Example时:基本关系模式 我有这个代码 它运作良好,但是在指南中,该模型应为: 为什么我不需要或在我的示例中?什么时候应该使用其中一个? 问题答案: 如果使用,则无需在第二个表上声明关系。 如果 不 使用,并分别定义,则如果不使用,则sqlalchemy将不知道如何连接关系,因此修改一个也将修改另一个。 因此,在您的示

  • 问题内容: 我在理解类中方法的含义时遇到问题。在下面的代码中,如果我使用该方法,则不使用它也会得到相同的结果。 为什么(或何时)需要使用它? 问题答案: 只创建一个对象 方法由调用

  • 问题内容: 我使用类只有很短的时间,编写方法时,我使所有变量都引用了self,例如self.foo。 但是,我在浏览《 wxPython in Action》 一书时发现,“ self”并没有一直使用。例如: 下面的一个确实使用“自我”。 如果我没记错的话,“自我”是指该类的特定实例,那么什么时候没有必要?有一般的经验法则吗? 问题答案: 您用于引用当前实例的属性。 您用于引用父类的方法。 如果仅