📜 ⬆️ ⬇️

Bad and good singletons

A lot of nasty things have already been said about the Singleton gang of four. You can read about the various principles of Singleton that are violated, for example, here . And it seems I have something to add.

The root cause of all the trouble with GoF Singleton is that for the vast majority of classes, Singleton is a part of their implementation. Simply, these classes are more convenient to implement, if the entire system works with a single object of each. GoF advises this implementation detail for all Singletons to be brought out, in the form of the getInstance () method.

And what if it becomes necessary to implement a class differently? Problems will begin. If the new implementation is no longer Singleton, then you will have to change not only the class itself but also all of its clients, removing all getInstance () calls and thinking through the strategy of creating instances for each case anew.

Is there any way to hide this class “Singleton property” from its customers, along with all the problems and principles that are being violated? Exists. This can be done using the architectural pattern Dependency Injection / Inversion of Control (IoC). The IoC container (IoCC) hides the class "Singleton 'ovozost" from its customers and takes all the responsibility of managing dependencies, freeing Singleton from: "... and provides a global access point to it ..." from the definition of the gang of four. The global access point is no longer needed, Singleton's clients no longer know exactly how many instances of the dependency class create IoCC for them. For example, my favorite IoCC Google Guice allows you to annotate a class with a Singleton annotation, but most importantly: it allows you to remove this annotation at any time without having to change class clients. Under the IoCC control, “Singleton'ovost” always remains a detail of the implementation of a class labeled as Singleton .
There are exceptions, when “Singleton'ovost” really should be a property of the class interface, and not a detail of its implementation. One such exception: Flyweight Singleton. For example, we write classes for an abstract syntax tree of the SQL language, and one of these classes would be SqlNull. It is desirable that this class have a single object, so that everyone knows about it, and compare this object with the others only by reference. In this case, GoF Singleton suits us perfectly.

So. For service classes, i.e. for most cases, Singleton is a implementation detail and IoCC allows it to hide; for Flyweight, Singleton is part of the interface, and you can put it out as suggested by GoF with getInstance ().

Source: https://habr.com/ru/post/102768/

All Articles