Вопрос: Что так плохо о одиночных играх? [закрыто]


singleton pattern является полностью оплаченным членом GoF «s книга моделей , но в последнее время это кажется сиротой мира разработчиков. Я все еще использую довольно много одиночек, особенно для заводские классы , и, хотя вы должны быть немного осторожны в вопросах многопоточности (например, в любом классе), я не понимаю, почему они так ужасны.

Переполнение стека, по-видимому, предполагает, что все согласны с тем, что синглтоны являются злыми. Зачем?

Пожалуйста, поддержите свои ответы с помощью " факты, ссылки или конкретные знания "


1719


источник


Ответы:


Перефразируемый от Брайана Баттона:

  1. Как правило, они используются в качестве глобального экземпляра, почему это так плохо? Потому что вы скрываете зависимости вашего приложения в своем коде, вместо того, чтобы разоблачать их через интерфейсы. Сделать что-то глобальное, чтобы избежать его прохождения, - это запах кода ,

  2. Они нарушают принцип единой ответственности : в силу того, что они контролируют собственное творение и жизненный цикл.

  3. Они по своей сути заставляют код плотно соединенный , Это во многих случаях затрудняет их проверку.

  4. Они несут состояние на протяжении всей жизни приложения. Еще один удар по тестированию, так как вы можете закончить ситуацию, когда нужно заказать тесты, что не является большим для нетипичных тестов. Зачем? Потому что каждый модульный тест должен быть независимым от другого.


1127



Синглтоны решают одну (и только одну) задачу.

Конфликт ресурсов.

Если у вас есть ресурс, который

( 1 ) может иметь только один экземпляр и

( 2 ) вам нужно управлять этим единственным экземпляром,

тебе необходимо одиночка ,

Примеров мало. Файл журнала является большим. Вы не хотите просто отказаться от одного файла журнала. Вы хотите сбросить, синхронизировать и закрыть его должным образом. Это пример одного общего ресурса, которому необходимо управлять.

Редко, что вам нужен синглтон. Причина, по которой они плохи, состоит в том, что они чувствуют себя Глобальный и они являются полностью оплаченным членом GoF Шаблоны проектирования книга.

Когда вы думаете, что вам нужен глобальный, вы, вероятно, делаете ужасную ошибку дизайна.


396



Некоторые кодирующие снобы смотрят на них как на прославленный глобальный. Точно так же, как многие люди ненавидят идти к что есть другие, которые ненавидят идею когда-либо использовать Глобальный , Я видел, как несколько разработчиков идут на необычные длины, чтобы избежать Глобальный потому что они считали использование одного в качестве допущения отказа. Удивительно, но факт.

На практике одиночка шаблон - это просто метод программирования, который является полезной частью вашего инструментария понятий. Время от времени вы можете обнаружить, что это идеальное решение, и поэтому используйте его. Но используя его, чтобы вы могли похвастаться шаблон дизайна так же глупо, как и отказ от использования, потому что это просто Глобальный ,


305



Misko Hevery, из Google, содержит некоторые интересные статьи именно по этой теме ...

Синглтоны - патологические лжецы имеет пример единичного тестирования, который иллюстрирует, как синглеты могут затруднить определение цепочек зависимостей и запуск или тестирование приложения. Это довольно экстремальный пример злоупотребления, но тот момент, который он делает, остается в силе:

Синглтоны - это не что иное, как глобальное состояние. Глобальное состояние делает так, чтобы ваши объекты могли тайно завладеть вещами, которые не объявлены в их API, и, как результат, Singletons превращают ваши API в патологических лжецов.

Где все синглтоны ушли указывает на то, что инъекция зависимостей упростила получение экземпляров конструкторами, которые их требуют, что облегчает базовую потребность в плохих глобальных синглотах, осужденных в первой статье.


199



Я думаю, что путаница вызвана тем, что люди не знают реального применения шаблона Singleton. Я не могу это подчеркнуть. Синглтон не шаблон для обертывания глобалов. Шаблон Singleton следует использовать только для того, чтобы гарантировать, что один и только один экземпляр данного класса существует во время выполнения.

Люди думают, что Синглтон злой, потому что он использует его для глобалов. Именно из-за этой путаницы Синглтон смотрит вниз. Пожалуйста, не путайте Singletons и globals. Если использовать для этой цели, для которой он предназначался, вы получите экстремальные выгоды от шаблона Singleton.


103



One rather bad thing about singletons is that you can't extend them very easily. You basically have to build in some kind of decorator pattern or some such thing if you want to change their behavior. Also, if one day you want to have multiple ways of doing that one thing, it can be rather painful to change, depending on how you lay out your code.

One thing to note, if you DO use singletons, try to pass them in to whoever needs them rather than have them access it directly... Otherwise if you ever choose to have multiple ways of doing the thing that singleton does, it will be rather difficult to change as each class embeds a dependency if it accesses the singleton directly.

So basically:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

rather than:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

I believe this sort of pattern is called dependency injection and is generally considered a good thing.

Like any pattern though... Think about it and consider if its use in the given situation is inappropriate or not... Rules are made to be broken usually, and patterns should not be applied willy nilly without thought.


70



The singleton pattern is not a problem in itself. The problem is that the pattern is often used by people developing software with object-oriented tools without having a solid grasp of OO concepts. When singletons are introduced in this context they tend to grow into unmanageable classes that contain helper methods for every little use.

Singletons are also a problem from a testing perspective. They tend to make isolated unit-tests difficult to write. Inversion of control (IoC) and dependency injection are patterns meant to overcome this problem in an object-oriented manner that lends itself to unit testing.

In a garbage collected environment singletons can quickly become an issue with regard to memory management.

There is also the multi-threaded scenario where singletons can become a bottleneck as well as a synchronization issue.


65



A singleton gets implemented using a static method. Static methods are avoided by people who do unit testing because they cannot be mocked or stubbed. Most people on this site are big proponents of unit testing. The generally most accepted convention to avoid them is using the inversion of control pattern.


52



Singletons are also bad when it comes to clustering. Because then, you do not have "exactly one singleton" in your application anymore.

Consider the following situation: As a developer, you have to create a web application which accesses a database. To ensure that concurrent database calls do not conflict each other, you create a thread-save SingletonDao:

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

So you are sure that only one singleton in your application exists and all database go through this one and only SingletonDao. Your production environment now looks like this: Single Singleton

Everything is fine so far.

Now, consider you want to set up multiple instances of your web application in a cluster. Now, you suddenly have something like this:

Many singletons

That sounds weird, but now you have many singletons in your application. And that is exactly what a singleton is not supposed to be: Having many objects of it. This is especially bad if you, as shown in this example, want to make synchronized calls to a database.

Of course this is an example of a bad usage of a singleton. But the message of this example is: You can not rely that there is exactly one instance of a singleton in your application - especially when it comes to clustering.


42



  1. It is easily (ab)used as a global variable.
  2. Classes that depend on singletons are relatively harder to unit test in isolation.

34



Monopoly is the devil and singletons with non-readonly/mutable state are the 'real' problem...

After reading Singletons are Pathological Liars as suggested in jason's answer I came across this little tidbit that provides the best presented example of how singletons are often misused.

Global is bad because:

  • a. It causes namespace conflict
  • b. It exposes the state in a unwarranted fashion

When it comes to Singletons

  • a. The explicit OO way of calling them, prevents the conflicts, so point a. is not an issue
  • b. Singletons without state are (like factories) are not a problem. Singletons with state can again fall in two categories, those which are immutable or write once and read many (config/property files). These are not bad. Mutable Singletons, which are kind of reference holders are the ones which you are speaking of.

In the last statement he's referring to the blog's concept of 'singletons are liars'.

How does this apply to Monopoly?

To start a game of monopoly, first:

  • we establish the rules first so everybody is on the same page
  • everybody is given an equal start at the beginning of the game
  • only one set of rules is presented to avoid confusion
  • the rules aren't allowed to change throughout the game

Now, for anybody who hasn't really played monopoly, these standards are ideal at best. A defeat in monopoly is hard to swallow because, monopoly is about money, if you lose you have to painstakingly watch the rest of the players finish the game, and losses are usually swift and crushing. So, the rules usually get twisted at some point to serve the self-interest of some of the players at the expense of the others.

So you're playing monopoly with friends Bob, Joe, and Ed. You're swiftly building your empire and consuming market share at an exponential rate. Your opponents are weakening and you start to smell blood (figuratively). Your buddy Bob put all of his money into gridlocking as many low-value properties as possible but his isn't receiving a high return on investment the way he expected. Bob, as a stroke of bad luck, lands on your Boardwalk and is excised from the game.

Now the game goes from friendly dice-rolling to serious business. Bob has been made the example of failure and Joe and Ed don't want to end up like 'that guy'. So, being the leading player you, all of a sudden, become the enemy. Joe and Ed start practicing under-the-table trades, behind-the-back money injections, undervalued house-swapping and generally anything to weaken you as a player until one of them rises to the top.

Then, instead of one of them winning, the process starts all over. All of a sudden, a finite set of rules becomes a moving target and the game degenerates into the type of social interactions that would make up the foundation of every high-rated reality TV show since Survivor. Why, because the rules are changing and there's no consensus on how/why/what they're supposed to represent, and more importantly, there's no one person making the decisions. Every player in the game, at that point, is making his/her own rules and chaos ensues until two of the players are too tired to keep up the charade and slowly give up.

So, if a rulebook for a game accurately represented a singleton, the monopoly rulebook would be an example of abuse.

How does this apply to programming?

Aside from all of the obvious thread-safety and synchronization issues that mutable singletons present... If you have one set of data, that is capable of being read/manipulated by multiple different sources concurrently and exists during the lifetime of the application execution, it's probably a good time to step back and ask "am I using the right type of data structure here".

Personally, I have seen a programmer abuse a singleton by using it as some sort of twisted cross-thread database store within an application. Having worked on the code directly, I can attest that it was a slow (because of all the thread locks needed to make it thread-safe) and a nightmare to work on (because of the unpredictable/intermittent nature of synchronization bugs), and nearly impossible to test under 'production' conditions. Sure, a system could have been developed using polling/signaling to overcome some of the performance issues but that wouldn't solve the issues with testing and, why bother when a 'real' database can already accomplish the same functionality in a much more robust/scalable manner.

A Singleton is only an option if you need what a singleton provides. A write-one read-only instance of an object. That same rule should cascade to the object's properties/members as well.


30