【问题标题】:A Singleton should be inheritable or not?单身人士应该是可继承的还是不可继承的?
【发布时间】:2012-02-24 09:51:15
【问题描述】:


单例应该是可继承的还是不应该是?

根据 Gof “当唯一的实例应该可以通过子类化扩展时,客户端 应该能够在不修改其代码的情况下使用扩展实例。”

但是为什么我会在 MSDN 上看到 Sealed 和 Private 构造函数示例

【问题讨论】:

  • 您使用单例的原因是什么?尽量不要。
  • 阅读单例标签维基。 stackoverflow.com/tags/singleton/info
  • @Adrian:好吧,我认为如果我不密封单例类,初级程序员可能会继承它并可能破坏单例模式导致子类单例的多个实例化,这就是为什么它应该被密封.
  • 但是我看到 Gof “实例应该可以通过子类化来扩展”。
  • "如果你想将继承与单例模式结合使用,你应该将可继承的状态和行为放入一个抽象基类中,并将单例定义为(最终)子类。"取自stackoverflow.com/questions/2573492/…

标签: c# design-patterns inheritance singleton


【解决方案1】:

在我的项目中,我使用了 Mark Seemanns 的 .NET 中的依赖注入一书中的环境上下文实现。该模式的主要使用点是,当您请求当前实例时,必须有一些东西,并且上下文可以由其他实现切换。 F.E.

public class TimeContext
{
    private static TimeContext _instance;

    public static TimeContext Current
    {
        get
        {
            if (_instance == null)
            {
                _instance = new DefaultContext();
            }
            return _instance;
        }
        set
        {
            if (value != null)
            {
                _instance = value;
            }
        }
    }
    public abstract DateTime GetDateTime();
}

上下文的具体实现应该是这样的:

public class DefaultContext : TimeContext
{
    public DateTime GetDateTime()
    {
        return DateTime.Now();
    }

}

【讨论】:

  • f.e.- 例如;不仅要使用默认创建来避免获取可为空的对象,而且当您想使用 setter 模拟默认实现时,它也适用于单元测试
  • 感谢增加我的词汇“环境上下文”和“依赖注入”对我来说是新的:)
  • 嘿,Ivan,我对继承有了你的想法,但也请看看这个“为什么我在 MSDN 上看到 Sealed 和 Private 构造函数示例”
  • 不是两个例子(来自 Ivan 和 Avner Shahar-Kashtan)相同吗?
  • 我不认为我们是一样的。我的解决方案允许您注入可作为全局范围使用的 TimeContext(在本例中为 DefaultContext)的具体实现。同样在单元测试期间,当您想使用另一个日期时间提供程序 (TestDateTimeContext:TimeContext) 时,您可以在测试中使用它并切换实现以模拟时间...
【解决方案2】:

我认为你在这里混合了两种不同的东西。单例模式调用所有调用者使用的单个实例。继承只是意味着我可以在类层次结构之间共享通用逻辑。我觉得这是单例模式的实现: (忽略缺少锁定/线程安全,为了示例)

public class Singleton
{
    private static Singleton _instance;
    public static Singleton Instance
    {
         get 
         { 
            if (_instance == null)
            {
                 // This is the original code.
                 //_instance = new Singleton();

                 // This is newer code, after I extended Singleton with
                 // a better implementation.
                 _instance = new BetterSingleton();
            }
            return _instance;
         }
    }

    public virtual void ActualMethod() { // whatever }
}

public class BetterSingleton : Singleton
{
    public override void ActualMethod() { // newer implementation }
}

我们仍然有一个单例,通过单例类的静态实例成员访问。但是该实例的确切身份可以通过子类化来扩展。

【讨论】:

  • 感谢您为此回复 +1,现在“DoARuntimeCheck()”有什么作用?一些 cmets 会有所帮助:)
  • 我建议在运行时确定特定的单例实现的可能性。我将代码更改为更简单的版本。
  • 这里,我改变了它来模拟项目随时间的变化:我们以前使用 Singleton,现在我们使用 BetterSingleton。但是因为我们使用了继承,调用 Singleton.Instance.ActualMethod() 的代码不知道也不关心我们切换了实现。
  • 不是两个例子(来自 Ivan 和 Avner Shahar-Kashtan)相同吗?
  • 类似,除了 Ivan 允许用户替换实例,而在我的情况下,它是在程序启动期间确定并从那里修复的。
猜你喜欢
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 2011-10-28
  • 2013-09-26
  • 2011-05-23
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
相关资源
最近更新 更多