Java 单例和静态类案例研究

Java 单例和静态类案例研究,java,singleton,static-class,Java,Singleton,Static Class,这已经是单例类和静态类之间的区别了。然而,我知道两者的区别,每次我需要选择的时候,我仍然感到困惑 因此,我为自己定义了两种不同的情况——我主要为POJO类(在java中)使用单音,如果该类只有一个实例(非常罕见),则为所有服务类使用静态类(经常出现) 例如,在我的应用程序中,我需要存储消息(我有一个可序列化的类消息),将它们写入文件,从文件读取,并在运行时访问。我不认为有任何理由在这里使用singleton,静态类是可以的。唯一的静态类是MessageStorage,它有3个函数-读取、写入和获

这已经是单例类和静态类之间的区别了。然而,我知道两者的区别,每次我需要选择的时候,我仍然感到困惑

因此,我为自己定义了两种不同的情况——我主要为POJO类(在java中)使用单音,如果该类只有一个实例(非常罕见),则为所有服务类使用静态类(经常出现)

例如,在我的应用程序中,我需要存储消息(我有一个可序列化的类消息),将它们写入文件,从文件读取,并在运行时访问。我不认为有任何理由在这里使用singleton,静态类是可以的。唯一的静态类是MessageStorage,它有3个函数-读取、写入和获取消息,还有一个消息的静态私有arraylist

这种方法合理吗?如果不合理,有什么问题吗?

理想的设计:-)

  • MessageStore应该是一个接口
  • MessageStoreFactory应该是一个带有getMessageStore()方法的单例(如果getMessageStore()每次都返回相同的消息存储,这不是问题,并且您有自己的单例)
  • 然后可以有多个MessageStore实现,如FileMessageStore、JDBCMessageStore、SubversionMessageStore等
  • 最重要的是,您可以使用MockMessageStore来模拟消息存储,并能够独立于消息存储测试依赖于消息存储的组件(并隔离任何故障)。例如,如果您正在测试MessageView并得到一个错误,您可以确保错误在MessageView中,而不是在静态MessageStore中,因为MockMessageStore是正确的

不管怎么说,这就是那些酷酷的孩子们现在所做的。。。依赖注入而不是工厂,而是一步一步…

这里真正要理解的是c#/java有不同的内存组

您的所有类都将加载到名为“类装入器内存”的内存段中。如果你制作的东西是静态的,它会保留在类加载器内存中。它可以从那里使用,但只能有1个实例。类加载器内存没有垃圾收集器,在应用程序的生命周期中,所有东西都留在那里

创建一个类的实例,不管它是否是单实例,都意味着完成了内存复制,从类装入器内存复制类,并将其复制到存储实例的区域。实例可以被垃圾收集

选择singleton和static类之间的实际决策点是:

1) 您想要继承还是类的接口(如果需要单例)
2) 强制类具有与应用程序相同的生命周期是否有意义(即,您必须手动清除类或编写方法来执行此操作,这会不必要地增加代码,从而降低可维护性)。(如果不是这样,那么你想要单身)
3) 您的应用程序是否需要可扩展性和潜在的更改。现在,如果通过静态属性实现,Singleton通常被认为是一种反模式。这样做的原因是您投资于基础设施,比如在类上公开静态实例属性,这可能完全不是您将来想要的,因为您的单窗口应用程序可能突然变成多窗口应用程序,您需要重写代码。(重写代码表明设计不好,尤其是在其核心基础设施的情况下)

作为一般经验法则,我建议如下:

  • 任何有类范围变量的类,都应该是单例(因为需要潜在地扩展它)
  • 每个方法各自独立的任何类都应该是静态的
在Java中使用“单例”的两个主要原因是:

1) 因此,一些存储可以与其他“静态”类相关联

2) 其中,对于给定服务的不同子类(或接口实现),您可能有多个“单例”,并将单例作为标识要使用哪个特定服务的一种方式进行传递

当然,您可以使用“静态”类的静态字段来包含数据,而不是使用#1,但是通常使用subject类的单个实例来包含数据比使用其他类的多个静态成员更方便(在许多情况下,效率更高)

此外,在JDK中,有许多情况下,一个类实际上以定义“常量”的名义实现了多个“单例”。(例如,java.awt.font.TextAttribute。)


一般来说,与基于C的语言相比,Java中使用单例的动机更少,因为Java确实实现了真正的类关联(和类保护)静态数据,而不是C语言中使用的模糊伪装(如果伪装的话)的全局静态数据,因此一个类中可以有多个静态字段,而不需要使用“central”对象包含C语言中的字段。

全局状态/静态通常被认为是不好的形式,这就是为什么单例通常被认为是一种错误形式。“良好实践”是静态类和单例只能用于没有状态的帮助器方法(例如
Math.sqrt(4)
).那么,在这种情况下,对于消息,您会怎么做?在需要存储状态的情况下,您只需要对一个对象进行一次引用。单例模式本身并不能保证它的存在,但它将位于任何需要该信息的对象都可以全局访问的位置。这将产生相同的效果,但正如我在pos中所说的那样t、 不同之处在于可伸缩性和可更改性随着需求的变化而提高。创建一个类一旦达到singelton目标,您所需要做的就是在一个全局可查找的位置对它进行引用。如果您是单元测试(这有助于说明为什么是静态的