Про патер проектування Singleton банди чотирьох вже сказано багато всяких гидот. Про різні порушувані Singleton'ом принципи можна почитати, наприклад, тут. І, схоже, мені є що додати.
Першопричина всіх бід з GoF Singleton'ом, в тому, що для переважної більшості класів «Singleton'овість» - це деталь їх реалізації. Просто ці класи так зручніше реалізувати, якщо вся система буде працювати з одним єдиним об'єктом кожного. GoF радить цю деталь реалізації для всіх Singleton'ів виносити назовні, у вигляді методу getInstance ().
А що якщо виникне необхідність реалізувати клас по-іншому? Почнуться проблеми. Якщо нова реалізація більше не буде Singleton'ною, то доведеться змінювати не тільки сам клас але і всіх його клієнтів, прибираючи всі виклики getInstance () і продумуючи стратегію створення примірників для кожного випадку заново.
А чи існує взагалі спосіб сховати цю властивість «Singleton'овості» класу від його клієнтів, разом з усіма проблемами і порушуваними принципами? Існує. Це можна зробити за допомогою архітектурного патерну Dependency Injection/Inversion of Control (IoC). IoC контейнер (IoCC) приховує «Singleton'овість» класу від його клієнтів і забирає собі всю відповідальність з управління залежностями, звільняючи Singleton від: «… і надає до нього глобальну точку доступу "... з визначення банди чотирьох. Глобальна точка доступу більше не потрібна, клієнти Singleton'a більше не знають, скільки саме екземплярів класу-залежності створює для них IoCC. Наприклад, мій улюблений IoCC Google Guice дозволяє позначити клас анотацією Singleton, але найголовніше: він дозволяє прибрати цю анотацію в будь-який момент без необхідності змінювати клієнтів класу. Під контролем IoCC «Singleton'овість» завжди залишається деталлю реалізації класу, позначеного як Singleton.
Існують і винятки, коли «Singleton'овість» дійсно повинна бути властивістю інтерфейсу класу, а не деталлю його реалізації. Одне з таких винятків: Flyweight Singleton. Наприклад, ми пишемо класи для абстрактного синтаксичного дерева мови SQL, і одним з таких класів буде SqlNull. Бажано, що б у цього класу був один єдиний об'єкт, щоб всі про це знали, і порівнювали цей об'єкт з іншими тільки за посиланням. У цьому випадку GoF Singleton нам підходить відмінно.
Отже. Для класів-сервісів, тобто для більшості випадків, «Singleton'овість» - це деталь реалізації і заховати її дозволяє IoCC; для Flyweight Singleton'ів - це частина інтерфейсу, і виставити її назовні можна як пропонують GoF за допомогою getInstance ().
