什么是单身人士的替代品

时间:2009-08-19 15:21:34

标签: java design-patterns singleton

我们有一个包含应用程序配置信息的类。它曾经是一个单身人士。经过一些建筑评论后,我们被告知要删除单身人士。我们确实看到了在单元测试中不使用单例的一些好处,因为我们可以同时测试不同的配置。

如果没有单例,我们必须在代码中的任何地方传递实例。它变得如此混乱,所以我们编写了一个单独的包装器。现在我们将相同的代码移植到PHP和.NET,我想知道是否有更好的模式我们可以用于配置对象。

13 个答案:

答案 0 :(得分:127)

Google Testing blog有一系列关于避免使用Singleton的条目(为了创建可测试的代码)。也许这可以帮到你:

上一篇文章详细解释了如何将新对象的创建移动到工厂中,因此您可以避免使用单例。值得一读。

  

简而言之,我们将所有新运营商转移到工厂。   我们将具有相似生命周期的所有对象组合到一个工厂中。

答案 1 :(得分:15)

最好的方法是使用Factory模式。构造类的新实例(在工厂中)时,可以将“全局”数据插入到新构造的对象中,作为对单个实例的引用(存储在工厂类中)或通过复制相关实例数据进入新对象。

然后,所有对象都将包含以前在单例中生存的数据。我认为总体上没有太大差异,但它可以使您的代码更容易阅读。

答案 2 :(得分:5)

我可能会在这里说明显而易见的事情,但是有没有理由不能使用SpringGuice之类的依赖注入框架? (我相信Spring现在也可以用于.NET。)

这样,框架可以保存配置对象的单个副本,并且您的bean(服务,DAO,等等)不必担心查找它。

这是我经常采用的方法!

答案 3 :(得分:4)

如果使用Spring Framework,则可以创建常规bean。默认情况下(或者如果显式设置scope="singleton"),只创建一个bean实例,并在每次在依赖项中使用bean或通过getBean()检索时返回该实例。

您可以获得单个实例的优势,而无需耦合Singleton模式。

答案 4 :(得分:4)

另一种选择是传递你需要的东西,而不是向对象询问事物。

答案 5 :(得分:4)

不会将责任累积到单个配置对象,因为它将以一个难以理解和脆弱的非常大的对象结束。

例如,如果您需要另一个特定类的参数,则更改Configuration对象,然后重新编译使用它的所有类。这有点问题。

尝试重构代码以避免使用常见的全局和大Configuration对象。仅将所需参数传递给客户端类:

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

应该重构为:

 class Server {

    public Server(int port) {
       this.port = port;
    }
 }

依赖注入框架在这里会有很多帮助,但并不是非常严格要求。

答案 6 :(得分:1)

您可以使用静态方法完成单例的相同行为。 Steve yegge在this帖子中解释得非常好。

答案 7 :(得分:0)

是否只包含静态方法和字段的类?我不确定你的具体情况,但可能值得研究。

答案 8 :(得分:0)

也许也不是很干净,但你可以将你想要改变的信息位传递给创建单例的方法 - 而不是使用

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

您可以直接在应用程序启动时调用createSingleton(Information info)(以及在单元测试的setUp-Methods中)。

答案 9 :(得分:0)

取决于正在使用的工具/框架等。 使用依赖注入/ ioc工具,通过让di / ioc容器对所需的类使用单例行为(例如IConfigSettings接口),只需创建一个类的实例,通常仍然可以获得单例性能/优化。这仍然可以替代测试

或者,可以使用工厂创建类并在每次请求时返回相同的实例 - 但是为了测试它可以返回存根/模拟版本

答案 10 :(得分:0)

查看将配置作为回调接口的可能性。 因此,您的配置敏感代码将显示:

MyReuseCode.Configure(IConfiguration)

系统初始化代码将显示:

Library.init(MyIConfigurationImpl)

答案 11 :(得分:0)

您可以使用依赖项注入框架来减轻传递配置对象的痛苦。一个不错的是ninject,它具有使用代码而不是xml的优势。

答案 12 :(得分:-1)

单身人士并不邪恶,但设计模式存在缺陷。我有一个类,我只想在运行时创建它的单个实例,但希望在单元测试期间创建多个独立的实例,以确保确定性的结果。

DI使用Spring等是一个非常好的选择,但不是唯一的选择。