仔细阅读有关单身人士的事实(代码气味,而不是模式),我想知道:
如何重构我的代码以摆脱它们?
尽管几乎每个人都同意坏单身人士,好,坏,我找不到任何有关如何更换它们的实用建议。无论是非常微不足道还是非常艰难。
我可以想到一些方法,但所有这些方法似乎都极大地膨胀了我的代码。
例如,假设我有一个“全局”AppConfig
类,其中包含有关产品的许可证信息并描述用户可用的功能。
我能想到的是:
AppConfig
实例的每个项目类创建一个公共基类。 (不好意思:对于已经有基类的情况,例如表格,这是不可能的)setAppConfig
方法创建通用界面。 AppConfigFactory
个实例的全局AppConfig
(BAD:仅将问题转移到另一个类)我该怎么办?
编辑:澄清:我在代码中发现了一个不好的单例。现在我想重构我的代码以删除它。我正在寻求关于如何实现这一目标的提示和一般想法。
答案 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
和对象之间的关联是有条件的(即,仅在某些方法中需要它),则将其作为额外参数传递。