Or it's better to use another Design Pattern?
5 回答
几天前在这里回答了一个类似的问题,嘲笑 Singleton。原始帖子是针对 C#.Net 的,关于模拟单身人士的行为,但仍应适用。
至于单例模式,它本身并没有什么问题——在许多情况下,我们希望集中逻辑和数据。但是,单例和静态类之间有很大的区别。将你的单例构建为一个静态类,硬编码应用程序中每个消费者的实现——这使得单元测试非常困难!
您要做的是为您的单例定义一个接口,公开方法供您的消费者使用。反过来,您的消费者会被实例化它们的人传递对实现类的引用[通常这是您的应用程序,或者如果您熟悉依赖注入\控制反转,则为容器]。
正是这个框架,无论是谁在实例化消费者,都负责确保一个且只有一个实例是浮动的。从静态类到接口引用的飞跃真的不是那么大[如上面的链接所示],你只是失去了全局可访问实例的便利 - 我知道我知道,全局引用非常诱人,但卢克背弃了黑暗面,你也可以!
一般来说,最佳实践建议避免静态引用,并鼓励针对接口进行编程。请记住,仍然可以应用带有这些约束的单例模式。遵循这些指导方针,你应该对你的工作进行单元测试没有问题:)
希望这可以帮助!
单例!=公共静态类,而不是单例==单实例
缺乏可测试性是经典单例模型(返回实例的静态类方法)的主要缺点之一。就我而言,这足以重新设计任何使用单例的代码以使用其他设计。
如果您绝对需要一个单一的实例,那么 johnny g 建议的依赖注入和写入接口绝对是要走的路。
当我编写可以模拟的基于静态的单例时,我正在使用以下模式。代码是Java,但我想你会明白的。这种方法的主要问题是您必须将构造函数放宽到包保护(这有点打败了真正的单例)。作为旁注 - 该代码适用于模拟您的“静态”代码的能力,不一定只是简单地调用它
我通常只对享元对象或类似值对象使用单例。查看 IoC 容器(如上所述)可能是比单例更好的处理共享对象的方法。
考虑到在 Smalltalk(很多这些模式的起源)中,真假都是有效的单例:)
如果您必须使用单例(并且有理由这样做......但如果可能的话,我总是会尽量避免使用它)。我建议使用 IOC 容器来管理它。我不确定是否有适用于 Delphi 的。但是在 Java 中你可以使用 Spring,在 .NET 中你可以使用 Windsor/Castle。一个 IOC 容器可以持有 Singleton 并且可以注册不同的实现进行测试。
除了这个片段之外,这可能是一个太大的主题。