单身如何与仅填充静态字段的类不同?
答案 0 :(得分:36)
几乎每次我写一个静态类时,我最终都希望将它实现为非静态类。考虑:
由于这两点,非静态类使得为依赖它们的项目编写更可靠的单元测试成为可能。
然而,单例模式距离静态类只有半步之遥。您有点获得了这些好处,但是如果您通过`ClassName.Instance'直接在其他类中访问它们,那么您将创建一个访问这些好处的障碍。就像ph0enix指出的那样,使用依赖注入模式会更好。这样,可以告诉DI框架特定类是(或不是)单例。您可以获得模拟,单元测试,多态性以及更多灵活性的所有好处。
答案 1 :(得分:12)
让我总结一下:)
本质区别在于:单身的存在形式是一个对象,静态不是。这导致了以下几点:
最后但并非最不重要的是,每当你要实现一个单身人士时,请考虑重新设计你的想法,不使用这个上帝对象(相信我,你会倾向于把所有“有趣”的东西都放到这个班级)并使用一个名为“Context”的普通类,或类似的东西。
答案 2 :(得分:5)
一个单身人士可以懒惰地进行初始化。
答案 3 :(得分:3)
区别在于语言无关。 Singleton的定义是:“确保一个类只有一个实例并提供一个全局访问点。”一个只填充静态字段的类与单例不同,但在您的使用场景中它们可能提供相同的功能。但正如JRL所说,懒惰的启动是一个区别。
答案 4 :(得分:3)
我认为,重要的是面向对象编程中的“对象”。除少数情况外,我们应该限制使用静态类。那种情况是:
另一个重要的事情是单身是可扩展的。单身人士可以延长。在 Math 类中,使用final方法,避免了此类对象的创建和扩展。 java.lang.System 类也是如此。但是, Runtime 类是单个对象,而不是静态方法。在这种情况下,您可以为不同的目的覆盖 Runtime 类的继承方法。
您可以延迟创建Singleton对象,直到需要(延迟加载)。但是,对于静态方法类,没有条件这样的东西。如果你到达该类的任何静态成员,该类将被加载到内存中。
因此,静态方法类的最基本的好处是您不必创建对象,但如果使用不当,它将使您的代码从面向对象中删除。
答案 5 :(得分:2)
至少你可以更容易地用模拟或存根替换它来进行单元测试。但正如你所描述的那样,我并不是单身人士的忠实粉丝:它是伪装的全球变量。
答案 6 :(得分:2)
单例是一个只有一个实例的类,强制执行。该类可能具有状态(是的,我知道静态变量保持状态),并非所有成员变量或方法都需要是静态的。
变体将是这些对象的一小部分,如果所有方法都是静态的,这将是不可能的。
答案 7 :(得分:2)
单例类将有一个实例,通常每个类加载器只有一个实例。因此它可以有常规方法(非静态方法),并且可以在该特定实例上调用它们。
虽然只有静态方法的类,但实际上没有必要创建实例(因此大多数人/框架都会使这些类的类抽象化)。您将直接在类上调用方法。
答案 8 :(得分:1)
首先想到的是,如果你想使用只有静态方法和属性的类而不是单例,你必须使用静态初始化器来正确初始化某些属性。例如:
class NoSingleton {
static {
//initialize foo with something complex that can't be done otherwise
}
static private foo;
}
这将在类加载时执行,这可能不是你想要的。如果将它作为单例实现,你可以更好地控制整个shebang。但是我觉得在任何情况下使用单身都不是一个好主意。
答案 9 :(得分:0)
注意:这些示例都在C#中,因为这是我更熟悉的,但这个概念应该适用于Java。
忽略关于何时使用Singleton对象的争论,我所知道的一个主要区别是Singleton对象有一个可以传递的实例。
如果你使用静态类,你可以自己硬连接到特定的实现,并且无法在运行时改变它的行为。
使用静态类设计不佳:
public class MyClass
{
public void SomeMethod(string filename)
{
if (File.Exists(filename))
// do something
}
}
或者,您可以让构造函数接受特定接口的实例。在生产中,您可以使用该接口的Singleton实现,但在单元测试中,您可以简单地模拟接口并改变其行为以满足您的需求(例如,使其抛出一些模糊的异常)。
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
}
}
这并不是说静态类总是坏的,只是不适合文件系统,数据库连接和其他低层依赖的东西。
答案 10 :(得分:0)
单例的一个主要优点是您可以实现接口并从其他类继承。有时你有一组单身人士都提供类似的功能,你想要实现一个共同的界面,但负责不同的资源。
答案 11 :(得分:0)
Singleton Class: Singleton Class是每个类加载器只能存在单个实例的类。
帮助程序类(仅包含静态字段/方法的类): 没有此类的实例。只有字段和方法可以作为常量或辅助方法直接访问。
此blog中的这几行描述得非常好:
首先,Singleton模式非常好 如果你想创建一个有用 一个类的实例。为我的帮手 我们真的不想上课 实例化该类的任何副本。 你不应该使用的原因 Singleton类是因为这个 帮助类我们不使用任何 变量。单身人士会 如果它包含一组,那就很有用 我们只想要一组的变量 和那些使用的方法 变量,但在我们的帮助类中我们 不要使用除了之外的任何变量 传入(我们做出最后的)。 因此我不相信我们 想要一个单例实例,因为我们 不想要任何变量而我们不需要 希望任何人实例化这个类。 所以,如果你不想要任何人 实例化类,即 通常,如果你有某种 helper / utils类然后我用什么 我调用静态类,一个类 私有构造函数,仅限 由静态方法组成,没有任何 任何变量。