单身人士模式的替代品?

时间:2010-07-03 11:07:42

标签: singleton design-patterns

我现在已经使用ASP.NET和C#成为Web开发人员了一段时间,我想尝试通过使用最佳实践来提高我的技能。

我有一个网站。我想一次性加载设置,并在我需要的地方引用它。所以我做了一些研究,50%的开发人员似乎都在使用单例模式来做这件事。其他50%的开发人员都是蚂蚁单身人士。他们都讨厌单身人士。他们建议依赖注入。

为什么单身人士不好?加载网站设置的最佳做法是什么?它们应该只加载一次并在需要的地方引用吗?我将如何通过依赖注入来实现这一点(我是新手)?是否有人可以为我的方案推荐的样品?我也希望看到一些单元测试代码(对于我的场景)。

由于 布伦丹

4 个答案:

答案 0 :(得分:6)

一般来说,我避免使用单身人士,因为他们会使你的应用程序难以进行单元测试。单身人士难以嘲笑单位测试,因为他们的性质 - 你总是得到同一个,而不是你可以轻松配置的单元测试。配置数据 - 无论如何强类型配置数据 - 是我做的一个例外。通常,配置数据相对来说是静态的,替代方法是编写大量代码以避免框架提供的静态类来访问web.config。

有几种不同的使用方法,仍然允许您对应用程序进行单元测试。一种方法(可能两种方式,如果您的单身人士不懒惰地阅读app.cofnig)是在单元测试项目中有一个默认的app.config文件,提供测试所需的默认值。您可以使用反射替换单元测试中所需的任何特定值。通常,我会配置一个私有方法,如果我确实对特定测试进行了更改,则允许在测试设置中删除私有单例实例。

另一种方法是不直接使用单例,而是为单例类实现它创建一个接口。您可以使用手动注入接口,如果提供的值为null,则默认为单例实例。这允许您创建一个模拟实例,您可以将其传递给测试中的测试类,但在您的实际代码中使用单例实例。本质上,每个需要它的类都维护对单例实例的私有引用并使用它。我喜欢这种方式更好一点,但是由于将创建单例,你可能仍然需要默认的app.config文件,除非所有的值都是延迟加载的。

public class Foo
{
    private IAppConfiguration Configuration { get; set; }

    public Foo() : this(null) { }

    public Foo( IAppConfiguration config )
    {
        this.Configuration = config ?? AppConfiguration.Instance;
    }

    public void Bar()
    {
         var value = this.Config.SomeMaximum;
         ...
    }
}    

答案 1 :(得分:1)

对单身模式进行了很好的讨论,这里的编码示例...... http://en.wikipedia.org/wiki/Singleton_pattern另见... http://en.wikipedia.org/wiki/Dependency_injection

出于某种原因,单身人士似乎将程序员分为强大的反阵营和反阵营。无论方法的优点是什么,如果你的同事反对它,最好不要使用它。如果您是独立的,请尝试并查看。

答案 2 :(得分:1)

设计模式可能是令人惊叹的事情。不幸的是,单身人士似乎像拇指疼痛一样突出,在许多情况下可以被认为是一种反模式(它促进了不良行为)。很可惜,大多数开发人员只会知道一种设计模式,那就是单身人士。

理想情况下,您的设置应该是高级别位置的成员变量,例如拥有您正在生成的网页的应用程序对象。然后,页面可以向应用程序询问设置,或者应用程序可以在构建页面时传递设置。

答案 3 :(得分:0)

解决此问题的一种方法是将其视为 DAL问题。

无论是哪个类/网页等都需要使用配置设置,都应声明对IConfigSettingsService(工厂/存储库/无论你喜欢调用它们)的依赖。

private IConfigSettingsService _configSettingsService;

public WebPage(IConfigSettingsService configSettingsService)
{
    _configSettingsService = configSettingsService;
}

所以你的班级会得到这样的设置:

ConfigSettings _configSettings = _configSettingsService.GetTheOnlySettings();

ConfigSettingsService实现将具有Dal类的依赖项。 Dal如何填充ConfigSettings对象? 谁在乎。

  • 每次都可能从数据库或.config xml文件中填充ConfigSettings。

  • 也许它是第一次这样做,但随后为后续调用填充静态_configSettings。

  • 也许它会从Redis获得设置。如果某些内容表明设置已更改,则dal或外部设备可以更新Redis。 (如果您使用多个设置有多个应用程序,此方法将非常有用。

无论它做什么,您唯一的依赖是非单一服务接口。这很容易嘲笑。在您的测试中,您可以让它返回一个ConfigSettings,其中包含您想要的任何内容)。

实际上,它更可能是具有IConfigSettingsService依赖关系的MyPageBase,但它可以很容易地成为Web服务,Windows服务,MVC somewhatsit或以上所有。