如何在实践中避免/重构坏单身?

时间:2009-07-29 07:25:37

标签: design-patterns oop

仔细阅读有关单身人士的事实(代码气味,而不是模式),我想知道:

如何重构我的代码以摆脱它们?

尽管几乎每个人都同意坏单身人士,好,坏,我找不到任何有关如何更换它们的实用建议。无论是非常微不足道还是非常艰难。

我可以想到一些方法,但所有这些方法似乎都极大地膨胀了我的代码。

例如,假设我有一个“全局”AppConfig类,其中包含有关产品的许可证信息并描述用户可用的功能。

我能想到的是:

  • 为包含AppConfig实例的每个项目类创建一个公共基类。 (不好意思:对于已经有基类的情况,例如表格,这是不可能的)
  • 使用setAppConfig方法创建通用界面。
  • 创建一个可以创建AppConfigFactory个实例的全局AppConfig(BAD:仅将问题转移到另一个类)
  • 将实例作为参数传递给需要它的每个方法。 (不好:代码臃肿)
  • ...

我该怎么办?

编辑:澄清:我在代码中发现了一个不好的单例。现在我想重构我的代码以删除它。我正在寻求关于如何实现这一目标的提示和一般想法。

4 个答案:

答案 0 :(得分:6)

使用依赖注入和控制反转框架 - 这可能需要进行大量重构。然后,使用构造函数或属性依赖,请求“单例” - 理想情况下,你不要求整个事情,因为根据Demeter的原则,它应该只询问它真正需要的东西(在你的情况下是许可证)信息)。

我试图区分Singleton(反模式伪装全局变量)和singleton(意味着你只需要其中一个)。在程序开始时(或在工厂中)创建一个真正的单例并传递给需要它的对象。

答案 1 :(得分:3)

你说

  

创建一个可以创建AppConfig实例的全局AppConfigFactory(BAD:仅将问题转移到另一个类)

在我看来,这实际上并不坏。客户端的观点是他向工厂对象询问他应该使用的配置。他知道它是单身人士!一下子,单身就被封装在工厂里。 [实际上工厂最终可能会成为一个单身人士,但一切都必须引导,对吗?]

现在,使用依赖注入技术封装Factory访问是否是一种改进,基本原则是只有一个对象正在创建这些AppConfig对象,只有工厂知道是否有一个或多个。

这导致我另一个宠物理论...没有这样的数字,当你开始它看起来像一个单身人士,然后复杂性增长,你发现你的应用程序的某些部分的情景(例如)使用一个配置而另一个部分使用不同的配置(例如,在版本之间的动态转换中)。工厂可以隐藏这种复杂性。

答案 2 :(得分:0)

如何让班级只有静态成员?比如,代替这个(C#代码):

class AppConfig
{
    public static readonly AppConfig Instance;

    private AppConfig() { }
    static AppConfig()
    {
        Instance = new AppConfig();
    }

    public string SomeConfigParam { get; set; }
}

这样做:

static class AppConfig
{
    public static string SomeConfigParam { get; set; }
}

单身人士只有在需要传递实例时才有意义 - 比如参数集合中的函数或值。 .NET中的System.DBNull是单例的一个很好的例子。如果它只是每个人都应该能够访问的全局数据存储,那么静态类可以使您的代码更简单,更简单。

答案 3 :(得分:0)

如果对象在其整个生命周期中需要app-config,则通过AppConfig方法或构造函数传递setAppConfig()。如果全局AppConfig和对象之间的关联是有条件的(即,仅在某些方法中需要它),则将其作为额外参数传递。