单身人士真的那么糟糕吗?[英] Are Singletons really that bad?

本文是小编为大家收集整理的关于单身人士真的那么糟糕吗?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

可能的重复:
Singletons有什么坏事?

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

我注意到这些天,我经常使用Singletons,我担心自己可能会滥用设计模式,并且越来越深入地养成了一种不良实践的习惯.

我们正在开发一个Flex应用程序,该应用程序在用户处理时具有非常大的层次数据结构.用户可以按需加载,保存,更改和刷新数据.

此数据是通过单顿类集合的,该类别汇总了几个数组汇编,数组,值对象以及通过Geters和seters暴露的其他本机成员变量.

要从应用程序中的任何地方获取对数据的引用,我们可以执行整个model.getInstance()方法的类型,我确定每个人都熟悉.这样可以确保我们始终掌握相同的数据副本,因为当我们设计时,我们说在应用程序寿命中只能存在一次实例.

从此中央数据存储库中,我们很容易就可以更容易地更改属性事件,并且可以具有多个UI组件来引用中央数据,更新其显示以反映发生的数据更改.

到目前为止,这种方法已经有效,并且对我们的情况非常实用.

但是,我发现,创建新课程时我有点过分渴望.诸如课程应该是单身人士之类的问题,或者应该将其其他方式管理,例如可能使用工厂,有时会变得有些困难,并且有些不确定性.

我在哪里与单身子一起绘制界线?有没有确定何时使用单例以及何时远离它们的好指南.

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

推荐答案

要记住的关键是,设计模式只是帮助您理解抽象概念的工具.一旦有了这种理解,将自己专门限制在书中的"食谱"是毫无意义的,并且会损害您编写最适合您目的的代码的能力.

也就是说,阅读像GOF这样的书将为您提供更多思考问题的方法,以便在您自己实施某些事情时,您将有一系列更广泛的观点来解决问题.

在您的情况下,如果在每种情况下使用Singleton都是有意义的,那么就继续前进.如果它"有点",您必须以某种笨拙的方式实现它,那么您需要提出一个新的解决方案.强迫不完美的图案有点像在圆孔中锤击正方形.

鉴于您说"这种方法对我们的情况非常有效,而且非常实用",我认为您的状况很好.

这里有一些好书:

四本书的帮派 - 用于设计模式

头部首次设计模式 - 听到了一些人的建议作为替代方案

其他推荐答案

是的,单例很糟糕.它们很糟糕,因为他们为您所做的就是结合两个属性,每个属性大约有95%的时间不好. (这意味着平均而言,单例的时间为99.75%;))

由GOF定义的单身人士是一个数据结构:

  1. 授予全球访问对象的访问,
  2. 强制执行该对象的一个​​实例.

第一个通常被认为是一件坏事.我们不喜欢全球群体. 第二个更加微妙,但通常,几乎没有任何情况是,这是对 emforce .

的合理限制.

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

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

单身人士隐藏依赖性并增加耦合(每个类都可以取决于单身人士,这意味着除非我们也重复使用所有单例,否则不能在其他项目中重复使用),并且因为这些依赖关系无法立即可见(AS as as as aS函数函数/构造函数参数),我们不会注意到它们,通常在创建它们时不会考虑它.只需拉一个单身人士,它几乎是局部变量,因此很容易,因此我们倾向于在那里使用它们很多.这几乎使它们不可能再次删除.您最终可能不是使用意大利面条代码,而是使用意大利面条依赖图.迟早,您的失控依赖性将意味着单身人士开始依靠彼此,然后在尝试初始化时会获得圆形依赖.

他们很难进行单位测试. (您如何测试调用在单例对象上函数的函数?我们不希望行使实际的单例代码,但是我们如何防止它?

是的,单例不好.

有时,您真的想要一个全球.然后使用全局,而不是单身.

有时,非常非常非常非常非常非常,您可能会有一种情况,可以创建类的多个实例是一个错误,其中 不会在不引起错误的情况下完成. (关于我唯一能想到的唯一情况,甚至是人为的,是您代表一些硬件设备.您只有一个GPU,因此,如果您要将其映射到代码中的对象,它将有意义的是,只有一个实例可以存在).但是,如果您发现自己处于这种情况(又一次强调,多种情况会导致严重错误,而不仅仅是"我无法想到任何用例"),那么那个约束,但要做,也不使对象在全球上可见.

在极少数情况下,这两个属性中的每一个都可以有用.但是我想不出一种情况,即它们的组合将是一件好事.

不幸的是,很多人都想到了"单身人士是符合OOP的全球群体".不,他们不是.他们仍然遭受与全球群体相同的问题,此外, 引入了其他一些完全无关的问题.绝对没有理由喜欢单身人士而不是普通的旧全球.

其他推荐答案

软件开发人员似乎均匀地分为两个营地,具体取决于他们是偏爱理想主义的编码样式还是务实的编码风格:

  • 理想主义:从不使用单例模式.
  • 务实:避免 singleton模式.

就个人而言,我赞成务实的方法.有时,违反规则是有意义的,但是只有您真正了解自己在做什么并且愿意接受相关风险.如果您可以对以下有关特定用例的问题回答"是",那么单例模式可以产生一些实际的好处.

  • 您的应用程序外部的单例?数据库,排队服务和ESB都是单身模式的完全有效的宏示例.
  • 吻:您整个应用程序是否限于2-3个内部单例?
  • 干:那些单身人士是否固有地全球,因此会导致不得不将引用引用到您的应用程序中的几乎每个对象中? (例如,记录器或组件中介)?
  • 您的单例仅依赖彼此和/或操作环境?
  • 您是否确保为每个单身人士(包括内存管理注意事项)确保适当的启动和关闭序列?例如,"大中央"风格的线程池可能需要在main()中具有instance run()和shutdown()方法,以便仅当其操作的对象处于有效状态时,才能保证任务才能运行.<<<<<<<<<<<<<<<<<<<

本文地址:https://www.itbaoku.cn/post/627460.html

问题描述

Possible Duplicate:
What is so bad about Singletons?

It's understandable that many design patterns can in some cases be abused, and like mom always said: "Too much of a good thing isn't always good!"

I'm noticing that these days, I'm using Singletons a lot, and I'm worried that I might be abusing the design pattern myself, and running deeper and deeper into a bad-practice kind of habit.

We're developing a Flex application that has a quite a large hierarchical data structure kept in memory while the user works on it. The user can load, save, change and refresh the data on demand.

This data is centralized by means of a Singleton class, which aggregates a couple of ArrayCollections, Arrays, value objects and some other native member variables exposed via getters and setters.

To get a reference to our data from anywhere in the application, we do the whole Model.getInstance() method type of thing, that I'm sure everyone is familiar with. This ensures that we always get our hands on the same copy of data, since when we designed, we said that only once instance is allowed to exist during the application lifetime.

From this central data repository, it's then easy for us to for example, dispatch property changed events, and can have multiple UI components that reference the central data, update their displays to reflect the data changes that have occurred.

So far, this approach has been effective and proven very practical to our circumstances.

I'm finding however, that I'm a little overeager when creating new classes. Questions like should a class be a Singleton, or should it rather be managed some other way, like maybe using a factory for example, tend to sometimes become a bit difficult, with a bit of uncertainty.

Where do I draw the line with singletons? Is there a good guideline for deciding when to use Singletons and when to stay away from them.

Also, can anyone recommend a good book on design patterns?

推荐答案

The key thing to remember is that design patterns are just a tool to help you understand the abstract concepts. Once you have that understanding, restricting yourself specifically to a "recipe" from a book is pointless and hurts your ability to write the code most appropriate for your purpose.

That said, reading books like GoF will present you with more ways to think about problems so that when the time comes to implement something on your own, you'll have a wider set of perspectives to approach the problem from.

In your case, if using singleton makes sense in every case, then go right ahead. If it "sort of" fits and you have to implement it in some clunky way, then you need to come up with a new solution. Forcing a pattern that isn't perfect is somewhat like hammering a square peg in a round hole.

Given that you say "this approach has been effective and proven very practical to our circumstances," I think you're doing fine.

Here are some good books:

Gang of Four Book - the classic book for design patterns

Head First Design Patterns - I've heard this recommended by a few people as an alternative

其他推荐答案

Yes, singletons are bad. They are bad because all they do for you is combine two properties, each of which is bad about 95% of the time. (Which would mean that on average, singletons are bad 99.75% of the time ;))

A singleton, as defined by the GoF, is a data structure which:

  1. Grants global access to an object, and
  2. Enforces that only one instance of the object can ever exist.

The first is generally considered a bad thing. We don't like globals. The second is a bit more subtle, but generally, there are virtually no cases where this is a reasonable restriction to enforce.

Sometimes, it only makes sense to have one instance of an object. In which case you choose to create only one. You don't need a singleton to enforce it.

And usually, even when it "makes sense" to have only one instance, it turns out not to make sense after all. Sooner or later, you're going to need more than one logger. Or more than one database. Or you're going to have to recreate resources for each of your unit tests, which means we have to be able to create them at will. It is prematurely removing flexibility from our code, before we understand the consequences.

Singletons hide dependencies and increase coupling (every class can potentially depend on a singleton, which means the class can not be reused in other projects unless we also reuse all our singletons), and because these dependencies are not immediately visible (as function/constructor parameters), we don't notice them, and typically don't think about it when we create them. It's so easy to just pull in a singleton, it acts almost as a local variable and all, so we tend to use them a lot once they're there. And that makes them almost impossible to remove again. You end up, perhaps not with spaghetti code, but with spaghetti dependency graphs. And sooner or later, your runaway dependencies will mean that singletons start depending on each others, and then you get circular dependencies when one is attempted initialized.

They make it extremely hard to unit-test. (How do you test a function that calls functions on a singleton object? We don't want the actual singleton code to be exercised, but how do we prevent that?

Yes, singletons are bad.

Sometimes, you really want a global. Then use a global, not a singleton.

Sometimes, very very very rarely, you may have a situation where creating multiple instance of a class is an error, where it can not be done without causing errors. (About the only case I can think of, and even that is contrived, is if you're representing some hardware device. You only have one GPU, so if you're going to map it to an object in your code, it would make sense that only one instance can exist). But if you find yourself in such a situation (and again, for emphasis, a situation where multiple instances cause serious errors, not just a situation where "I can't think of any use cases for more than one instance"), then enforce that constraint, but do it without also making the object globally visible.

Each of these two properties can be useful, in rare cases. But I can't think of a single case where the combination of them would be a good thing.

Unfortunately, a lot of people have got the idea that "Singletons are OOP-compliant globals." No, they're not. They still suffer the same problems as globals, in addition to introducing some other, completely unrelated ones. There is absolutely no reason to prefer a singleton over a plain old global.

其他推荐答案

Software developers seem to be pretty evenly split into two camps, depending on whether they favor an idealistic coding style or a pragmatic one:

  • Idealistic: Never use the singleton pattern.
  • Pragmatic: Avoid the singleton pattern.

Personally, I favor the pragmatic approach. Sometimes it makes sense to break the rules, but only if you really understand what you are doing and are willing to accept the associated risks. If you can answer "yes" to the questions below regarding your specific use case, the singleton pattern can yield some practical benefits.

  • Is the singleton external to your app? Databases, queuing services, and ESBs are all perfectly valid macro examples of the singleton pattern.
  • KISS: Is you entire app limited to 2-3 internal singletons?
  • DRY: Are those singletons inherently global and would therefore result in having to plumb references into almost every object in your app? (e.g., a logger or component mediator)?
  • Do your singletons depend only on each other, and/or the operating environment?
  • Have you ensured proper start-up and shut-down sequences for each singleton, including memory management considerations? For example, a "Grand Central"-style thread pool may need to have instance Run() and Shutdown() methods in main() so that tasks are guaranteed to run only when the objects they operate on are in a valid state.