Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的单例模式和静态类之间有什么区别?_Java_Design Patterns - Fatal编程技术网

Java中的单例模式和静态类之间有什么区别?

Java中的单例模式和静态类之间有什么区别?,java,design-patterns,Java,Design Patterns,singleton与只填充静态字段的类有何不同?至少您可以更轻松地用模拟或存根替换它,以进行单元测试。但我不是单例的忠实粉丝,原因正是你所描述的:它是伪装的全局变量。单例可以惰性地初始化,例如。单例是一个只有一个实例的类,强制执行。该类可能有state(是的,我知道静态变量保持state),但并非所有成员变量或方法都需要是静态的 一个变体是这些对象的一小部分,如果所有的方法都是静态的,这是不可能的。区别在于语言无关。根据定义,Singleton是:“确保一个类只有一个实例,并提供对它的全局访问点

singleton与只填充静态字段的类有何不同?

至少您可以更轻松地用模拟或存根替换它,以进行单元测试。但我不是单例的忠实粉丝,原因正是你所描述的:它是伪装的全局变量。

单例可以惰性地初始化,例如。

单例是一个只有一个实例的类,强制执行。该类可能有state(是的,我知道静态变量保持state),但并非所有成员变量或方法都需要是静态的


一个变体是这些对象的一小部分,如果所有的方法都是静态的,这是不可能的。

区别在于语言无关。根据定义,Singleton是:“确保一个类只有一个实例,并提供对它的全局访问点。”只填充静态字段的类与Singleton不同,但在您的使用场景中,它们可能提供相同的功能。但正如JRL所说,延迟初始化是一个区别。

一个单例类将有一个实例,通常每个类加载器只有一个实例。因此,它可以有常规方法(非静态)并且可以在特定实例上调用它们


虽然类只有静态方法,但实际上不需要创建实例(因此,大多数人/框架将此类Util类抽象化)。您只需直接调用类上的方法。

首先想到的是,如果您想使用只包含静态方法和属性的类而不是单例,则必须使用静态初始值设定项来正确初始化某些属性。例如:

class NoSingleton {
  static {
    //initialize foo with something complex that can't be done otherwise
  }
  static private foo;
}

这将在类加载时执行,这可能不是您想要的。如果您将它作为一个单例实现,那么您可以对整个shebang进行更多的控制。然而,我认为在任何情况下使用单例都不是一个好主意。

注意:这些例子都是用C#编写的,因为这是我比较熟悉的,但是这个概念应该同样适用于Java

忽略关于何时使用单例对象合适的争论,我知道的一个主要区别是单例对象有一个可以传递的实例

如果您使用静态类,您将自己硬连接到特定的实现,并且在运行时无法更改其行为

使用静态类的设计不佳:

public class MyClass
{
   public void SomeMethod(string filename)
   {
      if (File.Exists(filename))
        // do something
   }
}
或者,您可以让构造函数接收特定接口的实例。在生产环境中,您可以使用该接口的单例实现,但在单元测试中,您可以简单地模拟该接口并更改其行为以满足您的需要(例如,使其引发一些模糊的异常)


这并不是说静态类总是不好的,只是对于文件系统、数据库连接和其他低层依赖项来说,静态类不是一个很好的候选对象。

单例的主要优点之一是可以实现接口并从其他类继承。有时,您有一组单例,它们都提供类似的功能,您希望实现一个公共接口,但负责不同的资源

几乎每次我编写一个静态类时,我最终都希望我将它实现为一个非静态类。考虑:

  • 可以扩展非静态类。多态性可以节省大量重复
  • 一个非静态类可以实现一个接口,当您想要将实现与API分离时,这个接口很方便
由于这两点,非静态类使得为依赖于它们的项编写更可靠的单元测试成为可能


然而,单例模式离静态类只有半步之遥。您可以获得这些好处,但如果您通过“ClassName.Instance”在其他类中直接访问这些好处,则会对访问这些好处造成障碍。正如ph0enix指出的,使用依赖注入模式会更好。这样,可以告诉DI框架某个特定类是(或不是)单例。您可以获得模拟、单元测试、多态性和更多灵活性的所有好处。

单例类: Singleton类是每个类加载器只能存在一个实例的类

助手类(仅包含静态字段/方法的类): 不存在此类的实例。只有字段和方法可以作为常量或辅助方法直接访问

下面这几行很好地描述了它:

首先,单例模式非常简单 如果要创建一个,则此选项非常有用 类的实例。给我的助手 课堂上,我们真的不想 实例化类的任何副本。 你不应该使用 Singleton类就是因为这个 助手类,我们不使用任何 变量。单身阶级会 如果它包含一组 我们只需要一组变量 以及所使用的方法 变量,但在助手类中 不要使用除 通过的(我们最终确定)。 因为这个原因,我不相信我们 需要一个单例实例,因为我们 不需要任何变量,我们也不需要 想要任何人来实例化这个类。 所以如果你不想要任何人 实例化类,这是 通常,如果你有某种 helper/utils类,然后我使用what 我称之为静态类,一个具有 一个私有构造函数,并且只有 由静态方法组成,没有任何 任何变量

让我总结一下:)

本质上的区别是:单态的存在形式是对象,静态的不是。这导致了以下几件事:

  • 单例可以扩展。静态不是
  • 如果没有正确实现,单例创建可能不是线程安全的。静态不是
  • public class MyClass { private IFileSystem m_fileSystem; public MyClass(IFileSystem fileSystem) { m_fileSystem = fileSystem; } public void SomeMethod(string filename) { if (m_fileSystem.FileExists(filename)) // do something } }