【问题标题】:Should we seal Singletons? Should we try to inherit from Singletons in the first place?我们应该密封单身人士吗?我们应该首先尝试从单例继承吗?
【发布时间】:2010-04-04 03:49:20
【问题描述】:

是否应该允许 Singleton 类有孩子?我们应该密封它吗?优缺点是什么?

为了能够从 Singleton 类继承,我们必须使构造函数受保护而不是私有。现在,这在 c# 中会很好,但是 java 中的受保护字使子类和包类都可以访问构造函数。这意味着不仅继承自 Singleton 的类可以访问构造函数,同一个包中的其他类也可以访问。

我对所有这些事实有点困惑。也许我对没有什么可担心的事情大惊小怪?到现在为止,我从来没有必要尝试从 Singleton 继承,所以也许这只是一个学术问题!

谢谢

【问题讨论】:

    标签: c# java inheritance singleton


    【解决方案1】:

    是的,单身人士应该被密封。不,它们不应该被继承。

    原因是单例的主要(实际上)行为是在某个预定时间创建自身的实例。由于这个功能是静态的,它不能被覆盖,所以它必须被复制。一旦开始复制,就会有多个单例实例,这实际上没有任何意义。

    要么这样,要么你最终会遇到竞争条件或其他冲突,因为“派生”单例会争夺对全局实例的控制权,这不仅没有意义,而且很危险。

    Singleton 继承问题有一些 hackish 的解决方法,但它们就是这样 - hacks。单例模式并不适合继承。

    【讨论】:

    • 但是,如果构造函数是私有的,如何创建更多实例呢?只要不能调用构造函数,就不能创建实例。再说一次,我不明白为什么单例类应该用密封标记??
    • 我故意尝试继承非密封的单例类,我做不到。编译器给出错误消息:“'Singleton.Singleton()' 由于其保护级别而无法访问”。 Singleton 是我班级的名字。
    【解决方案2】:

    更好的解决方案是使用 IoC 容器框架来处理类的“单例”(生命周期)方面。此时,您可以使用 POJO 并简单地从它继承。

    编辑:一些可能有帮助的链接:

    寻找那些处理生命周期管理的。您希望能够配置容器(其行为类似于通用工厂),以便对“Singleton”类实例的请求始终返回相同的实例(至少对于相同的容器)。您的应用程序的最高级别通常只有一个容器实例。

    【讨论】:

    • IoC 也被描述为依赖注入 (DI)
    • +1。您应该将对象的生命周期(存在多少个实例)与对象中的实际逻辑/代码分开处理。将两者混合会导致丑陋。
    【解决方案3】:

    嗯,这听起来像是我们许多人在学习单身人士时在学校被问到的一个问题。我建议阅读以下链接。

    http://msmvps.com/blogs/jon_skeet/archive/2006/01/20/singleton-inheritance.aspx http://msdn.microsoft.com/en-us/library/84eaw35x.aspx

    许多人强烈反对从单例继承,但现实生活中的编程通常需要这种方法。我个人会说,作为经验法则,不要从单例继承,但不要将自己锁定在阻止这种方法的设计中。务实的开发方法永远是最好的方法...

    【讨论】:

    • “现实生活中的编程通常需要这种方法”[需要引用]
    • “很多人强烈反对从单例继承”——我首先强烈反对使用单例(或其他全局数据)。
    • @TrueWill,我明白你的意思,但软件项目的现实迫使我们采用技术方法。例如,我在 5 年前为一家大型银行开发了一个企业贷款网络应用程序。它有清晰分离的层处理数百个报告层,每个层执行特定的 XSLT 转换。然而,并发用户的数量增长得如此之快,以至于我们在生产服务器上物理上耗尽了内存。我们能够将内存使用量减少到 1/50,只需将全局静态变量用于只需要读取 1 次且所有会话都保持一致的信息。
    • 当然需要缓存或池化有限的资源是现实。全局静态和单例并不是实现这一目标的唯一方法。使用依赖注入可以实现相同的目标,尤其是在使用 DI/IoC 容器框架时。这可以提高可测试性和可维护性。
    【解决方案4】:

    如果您可以从单例扩展,那么这意味着您可以拥有多个它的实例。这与整个单例想法相矛盾。只需将其设为“普通”类并相应地围绕它编写代码,以便您只实例化一次并永远使用同一个实例。如果你需要它。依赖注入在这方面有很大帮助。

    【讨论】:

    • 这并不意味着它可以有多个实例。但是,必须有一种机制来确保子类可以将它们的实例设置为 实例。
    • 只有当构造函数是私有的并且实例是静态的时才有可能。总而言之,它没有任何意义。只实例化一个简单的类并在应用程序的生命周期中永远使用它有多难?
    • 我想我们只是误会了对方。我的意思是从单例类扩展并不完全意味着它可以有多个实例。
    【解决方案5】:

    如果要将继承与单例模式结合使用,则应将可继承的状态和行为放入抽象基类中,并将单例定义为(最终)子类。

    【讨论】:

      猜你喜欢
      • 2023-04-04
      • 2019-10-02
      • 2012-02-24
      • 1970-01-01
      • 2010-12-12
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      相关资源
      最近更新 更多