Навіщо використовувати синглтон замість статичних методів?


93

Я ніколи не знайшов хороших відповідей на ці прості запитання про допоміжні / допоміжні класи:

Чому б я створив синглтон (без стану) замість використання статичних методів?

Навіщо потрібен екземпляр об’єкта, якщо об’єкт не має стану?



Не думайте, оскільки ми говоримо про 2 різні мови, тому відповідь може бути різною, але дякую за посилання, в Java ніколи не чули терміну "монодержава"
Себастьян Лорбер,

Відповіді:


79

Часто одиночні використовуються для введення якогось глобального стану в програму. (Чесно кажучи, частіше, ніж насправді потрібно, але це тема для іншого часу.)

Однак є кілька кутових випадків, коли навіть одиночний файл без громадянства може бути корисним:

  • Ви очікуєте, що в найближчому майбутньому його можна буде розширити разом із державою.
  • Вам потрібен екземпляр об’єкта з певних технічних причин.
    Приклад: Об'єкти синхронізації для оператора C # lockабо Java synchronized.
  • Вам потрібно успадкування, тобто ви хочете мати можливість легко замінити свій синглтон на інший, використовуючи той самий інтерфейс, але іншу реалізацію.
    Приклад: Toolkit.getDefaultToolkit()Метод у Java поверне синглтон, точний тип якого залежить від системи.
  • Вам потрібна контрольна рівність для вартового значення .
    Приклад: DBNull.Valueу C #.

27
Я піду з +1, хоча одиноких людей IMHO зловживають для введення глобальних держав. Призначення одиночного не полягає в тому, щоб зробити об'єкт глобально доступним, а в тому, щоб примусити об'єкт інстанціюватися лише один раз. Глобальні об’єкти - це необхідне зло. Якщо це дійсно не потрібно, потрібно намагатися не використовувати їх, оскільки вони, як правило, призводять до високого зчеплення, де SomeSingleton.getInstance (). SomeMethod () всюди. :)
back2dos

Це може бути корисно в іграх, де вам потрібен лише один екземпляр візуалізації замість кількох екземплярів візуалізації, або з класом мережевих трубопроводів, де ви налаштовуєте захищений канал, що одночасно може бути лише одне підключення.
Чаллачка

2
"легко замінити синглтона" частина є найважливішим моментом з моєї точки зору. Відпочинок досить близький до реалізації статичного класу.
Teoman shipahi

1
Синглтони - це корисні ненульові вартові значення для суми / типів товарів та подібні. Наприклад, значення None / Nothing у типі Option або значення Empty для типу колекції. Ви отримуєте швидке тестування None / Empty як бонус, тому що все, що потрібно, - це контрольна рівність.
йогобрюце

@itsbruce: Ваші приклади не одинаки : Порожній список не є єдино можливим екземпляром класу List, а значення None не єдиним можливим екземпляр класу Option. Однак є приклад, коли вартове значення - одиночні, і я дозволив собі додати одне до своєї відповіді. Дякуємо за вхід!
Хайнзі,

37

Я міг бачити випадок, коли замість статичного методу, а саме для введення залежностей, використовується однотонний файл без стану .

Якщо у вас є допоміжний клас допоміжних функцій, які ви використовуєте безпосередньо, це створює приховану залежність; у вас немає контролю над тим, хто може ним користуватися і де. Ін'єкція того самого допоміжного класу через екземпляр одиночного елемента без стану дозволяє вам контролювати, де і як він використовується, і замінювати його / знущатись над ним тощо, коли вам потрібно.

Якщо зробити його екземпляром-одиночкою, це просто гарантує, що ви не виділяєте більше об’єктів типу, ніж потрібно (оскільки вам потрібен лише один).


1
"у вас немає контролю над тим, хто може ним користуватися і де." Навіщо комусь це потрібно?
hagrawal

1
@hagrawal для тестування, ти повинен мати можливість знущатися над ним
Джемшит Іскендеров

15

Насправді я знайшов іншу відповідь, не згадувану тут: статичні методи важче перевірити.

Здається, більшість тестових фреймворків чудово працюють для знущань над методами екземплярів, але багато з них не справляються гідно з макетом статичних методів.


2
Але, здається, Powermock може це зробити
Себастьян Лорбер

6

У більшості мов програмування класи уникають багатьох типів системи. Хоча клас зі своїми статичними методами та змінними є об'єктом, він дуже часто не може реалізувати інтерфейс або розширити інші класи. З цієї причини його не можна використовувати в поліморфному порядку, оскільки він не може бути підтипом іншого типу. Наприклад, якщо у вас є інтерфейс IFooable, який вимагається підписами декількох методів інших класів, об'єкт класу StaticFooне можна використовувати замість IFooable, тоді як FooSingleton.getInstance()можна (припускаючи, FooSingletonреалізує IFooable).

Зверніть увагу, що, як я коментував відповідь Хайнці, синглтон є шаблоном управління екземпляром. Він замінює new Class()на Class.getInstance(), що дає автору Classбільше контролю над екземплярами, які він може використовувати для запобігання створенню непотрібних екземплярів. Сінглтон - це лише особливий випадок заводського зразка, і його слід розглядати як такий. Загальне використання робить це досить особливим випадком глобальних реєстрів, що часто закінчується погано, оскільки глобальні реєстри не повинні використовуватися просто волею-неволею.

Якщо ви плануєте надати загальні допоміжні функції, то статичні методи будуть працювати прекрасно. Клас не буде діяти як клас, а скоріше просто як простір імен. Я пропоную вам зберегти високу згуртованість, інакше у вас можуть виникнути найдивніші проблеми взаємозв'язку.

Greetz
back2dos


4

Існує компроміс між використанням якого. Одиночні можуть мати або не мати стан, і вони стосуються об'єктів. Якщо вони не зберігають стан і використовуються лише для глобального доступу, тоді статичний краще, оскільки ці методи будуть швидшими. Але якщо ви хочете використовувати об'єкти та концепції ООП (поліморфізм успадкування), тоді краще використовувати одиночний.

Розглянемо приклад: java.lang.Runtime - це синглтон-клас у Java. Цей клас дозволяє різні реалізації для кожного JVM. Реалізація є однією для JVM. Якщо цей клас був би статичним, ми не можемо передавати різні реалізації на основі JVM.

Я знайшов це посилання справді корисним: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

Сподіваюся, це допоможе !!


Ця відповідь хороша для включення конкретного прикладу в реальний світ.
системович

2

Для мене "Хочу, щоб стан об'єкта використовував Singleton, Функція Want використовував статичний метод"

Це залежить від того, що ви хочете. Всякий раз, коли вам потрібен стан об’єкта (наприклад, поліморфізм, наприклад, стан Null замість nullабо стан за замовчуванням), для вас підходить синглтон, тоді як статичний метод використовується, коли вам потрібна функція (Отримати входи, а потім повернути результат).

Я рекомендую для випадку singleton, він повинен бути завжди однаковим, після того, як його створити. Він не повинен бути закритим або отримувати будь-яке значення для встановлення (крім статичної конфігурації з файлу, наприклад, файл властивостей у Java).

PS Продуктивність між цими двома різниться в мілісекундах, тому спершу зосередьтеся на архітектурі .


1

Сінглтон не є без громадянства, він утримує глобальний стан.

Деякі причини, за якими я можу подумати, використовуючи Singleton:

  • Щоб уникнути витоків пам’яті
  • Надати однаковий стан для всіх модулів у програмі, наприклад, підключення до бази даних

Я знаю, але насправді синглтон може більш-менш бути без громадянства ... Якщо він не має жодного атрибута класу ...
Себастьян Лорбер,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.