【问题标题】:Why singleton breaks open/closed principle?为什么单例打破了开/关原则?
【发布时间】:2016-04-27 10:35:01
【问题描述】:

谁能告诉我为什么单例会打破打开/关闭原则? 是不是因为从那个类继承可能有问题?

【问题讨论】:

    标签: design-patterns singleton solid-principles


    【解决方案1】:

    对于一个“开放”的类,它必须可以从它继承。继承是一种“is-a”关系。如果您从单例类继承,则由于“is-a”关系,子类的实例也是父类的实例,这意味着您可能突然拥有多个单例类实例。

    如果单例类禁止继承,它就不再是“开放的”。

    如果单例类允许继承,并且对扩展是“开放的”,那么它就不能再强制执行单例模式。

    【讨论】:

    • 这是错误的。请参阅下面的答案。
    【解决方案2】:

    Singleton 设计模式禁止继承是一个常见的误解。这根本不是真的。

    来自 GoF 书,第 127 页:

    在以下情况下使用单例模式

    • 必须有一个类的实例,并且它必须是可访问的 来自知名接入点的客户端。
    • 当唯一的实例应该可以通过子类化和客户端进行扩展时 应该能够在不修改其代码的情况下使用扩展实例。

    ...再次在第 128 页:

    单例模式有几个好处:

    1. 允许优化操作和表示。 Singleton 类可以是 子类化,并且很容易使用 this 的实例配置应用程序 扩展类。您可以使用以下实例配置应用程序 运行时需要的类。

    第 130 页详细介绍了配置单例子类。

    为什么 Singleton 会破坏 OCP 的答案是它不会,至少不是天生的。它恰好是最常被未阅读 GoF 书籍的开发人员违反 OCP 实现的。工厂方法模式也面临同样的命运。

    【讨论】:

    • GoF 书中的例子是他们的MazeFactory 类,它实例化一个可以根据环境变量而变化的实例。
    • 你能举一个可扩展的单例实现的例子吗?
    • @jaco0646,等待对 Nir ​​在上述评论中所说的内容进行简单易懂的回应......
    • @IstiaqueAhmed,我建议阅读 GoF 书中的 Singleton 章节。其中很大一部分致力于子类化的主题。
    【解决方案3】:

    单例模式有两个问题:

    • 它打破了打开/关闭原则,因为单例类本身可以控制其实例的创建,而消费者通常会对其具体实例有硬依赖。这不允许更改实现,而无需在整个应用程序中进行全面更改。
    • 它打破了依赖倒置原则 (DIP),因为消费者将始终直接依赖具体类来获取实例,而 DIP 规定了使用抽象。这会导致单例实现被拖拽,并且不允许通过将实现包装在装饰器中或在没有单例实现的情况下分发客户端来添加横切关注点。

    【讨论】:

    • 单例不能实现一个接口来解决这两个问题吗?接口保持对扩展开放,而依赖于接口的客户端不需要知道他们都在使用抽象背后的单例实例。
    • 如果它有接口并且Instance 是可替换的,这将不是单例模式,Instance 属性仍将定义在静态类上,这会导致 DIP被违反。
    • 请看下面我的回答。
    • 嗨@jaco0646:这是一个很好的观察,单例可以被子类化。子类化确实可以修复 OCP 违规。然而,它仍然给我们留下了违反 DIP 的问题。
    • 你指的是Singleton Lifestyle,与Singleton设计模式关系不大。
    猜你喜欢
    • 1970-01-01
    • 2010-12-20
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    相关资源
    最近更新 更多