单身人士真的很糟糕吗?

可能重复:
单身人士有什么不好?

可以理解的是,许多设计模式在某些情况下可能会被滥用,就像妈妈总是这样说:“太多的好东西并不总是好的!”

我注意到这些日子里,我很多都在使用Singletons,而且我担心自己会滥用设计模式,并且越来越深入地陷入坏习惯习惯。

我们正在开发一个Flex应用程序,该应用程序在用户使用该应用程序时具有保存在内存中的相当大的分层数据结构。 用户可以根据需要加载,保存,更改和刷新数据。

这些数据通过一个Singleton类来集中,它聚集了几个ArrayCollections,Arrays,value对象和一些其他通过getter和setter公开的本地成员变量。

为了从应用程序中的任何位置获取对我们数据的引用,我们确定了所有人都熟悉的整个Model.getInstance()方法类型的事物。 这确保了我们始终掌握相同的数据副本,因为当我们设计时,我们说在应用程序生命周期中只允许存在一次实例。

从这个中央数据存储库中,我们可以轻松地例如调度属性更改的事件,并且可以有多个引用中央数据的UI组件,更新其显示以反映已发生的数据更改。

到目前为止,这种方法是有效的,并证明对我们的情况非常实用。

然而,我发现在创建新课程时我有点过激。 诸如类应该是Singleton这样的问题,还是应该用其他方式来管理,比如可能使用工厂,有时会变得有点困难,带有一些不确定性。

我在哪里画单行? 是否有一个很好的指导方针来决定何时使用Singletons以及何时离开它们。

另外,任何人都可以推荐一本关于设计模式的好书吗?


要记住的关键是设计模式只是帮助您理解抽象概念的工具。 一旦你有了这样的理解,将自己特别限制为书中的“配方”是没有意义的,并且会伤害你编写最适合你的目的代码的能力。

也就是说,像GoF这样的阅读书籍将为您提供更多思考问题的方法,以便在需要时间自行实施某些问题时,您将有更广泛的视角来解决问题。

在你的情况下,如果在任何情况下使用单例都是有意义的,那么就直接向前。 如果它“适合”并且你必须以一种笨重的方式实现它,那么你需要提出一个新的解决方案。 强制一个不完美的图案有点像敲击圆孔中的方形钉。

鉴于你说“这种方法是有效的,并证明对我们的情况非常实际,”我认为你做得很好。

这里有一些好书:

四本帮派 - 设计模式的经典之作

首先设计模式 - 我听说过一些人推荐这种替代方案


是的,单身人士是不好的。 他们是不好的,因为他们为你所做的就是结合了两个属性,每个属性在95%的时间内都不好。 (这意味着平均来说,单身人士在99.75%的时间内不好);)

由GoF定义的单例是一种数据结构,其中:

  • 授予对象的全局访问权限,以及
  • 强制只能有一个对象的实例存在。
  • 第一个通常被认为是一件坏事。 我们不喜欢全局变量。 第二点稍微微妙一点,但通常情况下,实际上并没有这种合理限制来执行的情况。

    有时,只有一个对象的实例才有意义。 在这种情况下,您只选择创建一个。 你不需要一个单例来执行它。

    通常,即使只有一个实例“有意义”,事实证明毕竟是没有意义的。 迟早,你将需要不止一个记录器。 或多个数据库。 或者你将不得不为每个单元测试重新创建资源,这意味着我们必须能够随意创建它们。 在我们理解后果之前,它过早地从我们的代码中删除了灵活性。

    单身隐藏的依赖,增加耦合(每类有可能依赖于一个单身,这意味着类不能在其他项目中重用,除非我们也重复使用我们所有的单身人士),因为这些依赖不是立即可见(如函数/构造函数的参数),我们没有注意到它们,并且在我们创建它们时通常不会考虑它们。 只需拉一个单例就很容易,它几乎作为一个局部变量和全部,所以我们倾向于一旦他们在那里使用它们。 这使得他们几乎不可能再次移除。 你最终可能不会使用意大利面代码,而是使用意大利面条依赖图。 迟早会出现失控的依赖关系,意味着单身人士会根据彼此开始工作,然后在尝试初始化时获得循环依赖关系。

    他们使单元测试非常困难。 (你如何测试一个函数调用单例对象的函数?我们不希望实际的单例代码被执行,但我们如何防止这种情况?

    是的,单身人士是不好的。

    有时候,你真的想要一个全球性的。 然后使用全局的,而不是单身。

    有时候,非常非常少见,您可能会遇到这样的情况,即创建一个类的多个实例是一个错误,在没有导致错误的情况下无法完成。 (关于我能想到的唯一情况,即使这是人为设计的,如果你代表一些硬件设备,你只有一个GPU,所以如果你想将它映射到代码中的一个对象,它会理解只有一个实例可以存在)。 但是,如果你发现自己处于这种情况下(并且再强调一下,多个实例导致严重错误的情况,而不仅仅是“我不能想到多于一个实例的任何用例”的情况),然后执行该约束,但是在没有使对象全局可见的情况下进行。

    在极少数情况下,这两个属性都是有用的。 但我不能想到一个案例,他们的组合将是一件好事。

    不幸的是,很多人都认为“Singletons是OOP兼容的全局”。 不,他们不是。 除了引入其他一些完全不相关的问题外,他们仍然遇到与全局相同的问题。 绝对没有理由比单纯的旧式全球更喜欢单身。


    软件开发人员似乎很平均分为两个阵营,这取决于他们是否偏爱理想主义的编码风格或实用的编码风格:

  • 理想主义:永远不要使用单身模式。
  • 务实:避免单身模式。
  • 就我个人而言,我赞成务实的态度。 有时候违反规则是有道理的,但前提是你真的了解自己在做什么并且愿意接受相关的风险。 如果您对以下针对您的具体使用案例的问题回答“是”,则单例模式可以产生一些实际益处。

  • 单身是你的应用程序的外部吗? 数据库,排队服务和ESB都是单例模式的完全有效的宏示例。
  • KISS:你的整个应用程序限于2-3个内部单身人士吗?
  • DRY:那些单身人士本身就是全球性的,因此会导致你不得不将你的应用程序中的几乎所有对象都引用到其中? (例如,记录器或组件介体)?
  • 你的单身人士是否只依赖彼此和/或操作环境?
  • 你是否确保每个单例都有正确的启动和关闭序列,包括内存管理考虑因素? 例如,“Grand Central”风格的线程池可能需要在main()中具有实例Run()和Shutdown()方法,以确保任务只有在它们操作的对象处于有效状态时才能运行。
  • 链接地址: http://www.djcxy.com/p/14427.html

    上一篇: Are Singletons really that bad?

    下一篇: Why does C# not provide the C++ style 'friend' keyword?