Різниця між статичним класом і однотонним малюнком?


1767

Яка реальна (тобто практична) різниця існує між статичним класом і однотонним малюнком?

Обидва можна викликати без ініціативи, обидва надають лише один "екземпляр", і жоден з них не є безпечним для потоків. Чи є якась інша різниця?


4
Залежно від мовної реалізації та способів використання, Singleton може бути менш ефективним через накладні виклики getInstance()методу щоразу, коли ви бажаєте його використовувати (хоча, мабуть, у більшості випадків це не має значення ).
занадто багато php

5
Відповідей уже багато. Насправді це singletonоб'єкт, де staticметоди - це лише функції, не є об'єктом OO.
fastcodejava

4
Залежить від реалізації. Csharpindepth.com/Articles/General/Singleton.aspx
VJAI

4
Існує різниця, коли ви хочете дозволити третім сторонам постачати реалізацію класу. У цьому випадку вам також потрібні фабричні візерунки. Дивіться agiletribe.wordpress.com/2013/10/08/…
AgilePro

IMO ця відповідь дуже добре підсумовує stackoverflow.com/questions/14097656/…
Дейв

Відповіді:


1251

Що змушує вас сказати, що ні однотонний, ні статичний метод не є безпечними для потоків? Зазвичай і те, і інше повинно бути безпечним для потоків.

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


29
Ну, якщо ви віддаєте перевагу, і це по суті не є безпечним для ниток, ви повинні зробити їх безпечними для ниток, обидва вони, тому різниці немає.
Хорхе Кордоба

119
Чи можете ви навести приклад чогось, що за своєю суттю є безпечним для потоків, окрім непорушних видів?
Джон Скіт

26
На Скіт: Люди, які говорять, що однотонний не є безпечним для потоків, означає, що сингл розділяється між потоками непотрібно весь час, а об'єкти стека діляться спільним, коли вам це потрібно, а це означає, що вам не потрібно робити непотрібну синхронізацію.

45
@Geek: Уявіть, що сингл реалізує інтерфейс Foo, і у вас є метод, що приймає Fooпараметр. За допомогою цього налаштування абоненти можуть обрати одиночну функцію в якості реалізації - або ж вони могли використовувати іншу реалізацію. Спосіб відокремлюється від одинарного. Порівняйте це із ситуацією, коли у класу є просто статичні методи - кожен фрагмент коду, який хоче викликати ці методи, щільно поєднаний з класом, оскільки йому потрібно вказати, який клас містить статичні методи.
Джон Скіт

10
@AmirBareket: Хоча це не синглтон за схемою дизайну синглів - якщо сам клас дозволяє створювати декілька екземплярів, це не одиночний IMO, незалежно від того, що робить фабрика.
Джон Скіт

476

Справжня відповідь - Джон Скіт, на іншому форумі тут .

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

Статичний клас дозволяє лише статичні методи.


64
Навіщо ви передаєте Singleton як параметр, якщо ви можете отримати доступ до одного і того ж екземпляра з будь-якого місця, зателефонувавши в статичний метод getInstance ()?
Анріке Ордін

23
@HenriqueOrdine Так він може вписуватися в існуючий код і надавати інтерфейс?

6
@HenriqueOrdine Вони говорять про статичний клас, а не про клас зі статичними методами. Статичний клас неможливо встановити. Тим не менше, якщо ви передаєте екземпляр класу (нестатичний), який містить статичні методи, ви не можете викликати статичні методи в екземплярі.
Горан

3
Що таке статичний клас? Принаймні, на Яві такого немає.
Анріке Ордін

16
@Goran Мене спочатку дуже бентежило твоє формулювання. Ви сказали, що "не можна викликати статичні методи в екземплярі". Я читаю, що як "якщо у вас є посилання на об'єкт, який не використовується, ви не можете викликати будь-які статичні способи". Це, звичайно, неправильно. Після декількох разів прочитавши його, я думаю, що ви мали на увазі «зсередини статичних методів ви не можете отримати доступ до нестатичних об’єктів у класі», що є правильним. Хочете уточнити, що для всіх, хто знайомий з цими поняттями, хто стикається з цією відповіддю та читає ваші коментарі.
Ендрю Штейц

359
  1. Об'єкти Singleton зберігаються в Heap , але статичні об'єкти зберігаються в стеці .
  2. Ми можемо клонувати (якщо дизайнер не заборонив це) однотонний об'єкт, але ми не можемо клонувати об’єкт статичного класу.
  3. Однокласні класи дотримуються ООП (об'єктно-орієнтовані принципи), статичні класи - ні.
  4. Ми можемо реалізувати interfaceкласу Singleton, але статичні методи класу (або, наприклад, C # static class) не можуть.

99
Друге твердження неправильне. Ми не можемо клонувати об'єкт Singleton. Реалізація Singleton повинна відмовитись від цього. Якщо ви дійсно можете клонувати Сінглтона, це не Сінглтон.
Олександр Янчарук

19
Ця відповідь не є правильною для Java: ні сингтон, ні статик не використовують стек.
AgilePro

72
№1 не важливо. №2 описує несправну реалізацію. №3 абсолютно невиправдано.
Кейсі

31
Як статичний об'єкт може зберігатися в стеці? Новий кадр стека створюється, коли ви викликаєте метод, він зберігає локальні змінні методу, цей кадр стека видаляється, коли метод повертається, і ці локальні змінні втрачаються. Впевнений стек є швидким, але він не підходить для зберігання статичних об'єктів.
mike_m

23
Я не можу зрозуміти кількість оновлень на цьому. 1) Чому Singleton потрібно зберігати в стеці? У керованих мовах, таких як C # або Java, дані зберігаються в керованій купі, за винятком локальних змінних / параметрів методу. 2) Якщо ви можете його клонувати, то це не належно реалізований синглтон. 3) Сінглтон відомий як анти-візерунок OOP; тобто чогось, чого вам слід уникати, якщо можливо. 4) Це єдине, що правильно.
Гроо

152

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


10
+1 за хороші, прагматичні моменти. Взагалі однотонний малюнок в основному використовується, але є кілька ситуацій, коли він підходить. Дивіться також: agiletribe.wordpress.com/2013/10/08/…
AgilePro

3
Ви маєте рацію щодо того, що ви є поліморфними. Це найважливіший момент
Ахмад

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

75

staticзаняття не для нічого, що потрібно державі. Це корисно для поєднання купу функцій, тобто Math(або Utilsв проектах). Тож назва класу просто дає нам підказку, де ми можемо знайти функції та більше нічого.

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

Моє правило вибору між staticта singleton:

Якщо є купа функцій, які слід зберігати разом, то staticвибір. Все інше , що потрібно єдиний доступ до деяких ресурсів, можуть бути реалізовані у вигляді singleton.


16
Чому статичні класи не повинні робити нічого, що потрібно для збереження стану?
Trisped

12
@Trisped: Ви не маєте ані точного контролю над ініціалізацією, ані завершенням.
Xaqron

7
ви втратили мене в "Singleton - мій улюблений зразок". Сінглтон - це такий гострий кут, що його слід вважати анти-візерунком, а також зразком. Класи цілком можуть мати статичні стани, це також одинарний доступ, якщо що-небудь статичне стан є більш "одинарним доступом", ніж одиночні, тому що більшість сингтонних реалізацій порушені, тобто. Ви можете клонувати синглтон, тоді як статичне благословляє визначення, щоб бути унікальним.
PoweredByRice

1
Що означає підтримувати державу? Що таке держава?
Кайл Делані

2
@KyleDelaney: Просто Stateце поєднання різних властивостей об'єкта, які зазвичай змінюються з часом. Ви можете скористатися формальним визначенням Google.
Xaqron

65

Статичний клас: -

  1. Ви не можете створити екземпляр статичного класу.

  2. Автоматично завантажується програмою загальної мови .NET Framework (CLR), коли завантажується програма або область імен, що містять клас.

  3. Статичний клас не може мати конструктор.

  4. Ми не можемо передати статичний клас методу.

  5. Ми не можемо успадкувати статичний клас до іншого статичного класу в C #.

  6. Клас, що має всі статичні методи.

  7. Більш висока продуктивність (статичні методи зв’язуються на час компіляції)

Синглтон: -

  1. Ви можете створити один екземпляр об'єкта і повторно використовувати його.

  2. Екземпляр Singleton створюється вперше, коли користувач запитував.

  3. Сингл-клас може мати конструктор.

  4. Ви можете створити об'єкт однокласного класу і передати його методу.

  5. Клас одиночки не говорить про обмеження спадкування.

  6. Ми можемо розміщувати об'єкти однотонного класу, але не статичного класу.

  7. Методи можуть бути відмінені.

  8. Можна ліниво завантажуватись при потребі (статичні класи завжди завантажуються).

  9. Ми можемо реалізувати інтерфейс (статичний клас не може реалізувати інтерфейс).


13
Статичні класи мають конструктори: msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
Tomer Arazy

2
Так, статичний може мати конструктор, який є внутрішнім для цього класу. Це викликається, коли викликається будь-який статичний метод у класі.
rahulmr

Для одиночного часу на час компіляції він зберігається в пам'яті HEAP, але якщо він інстанціюється один раз, він зберігається в STACK?
Luminous_Dev

@Luminous_Dev Ні. Будь-який одиночний екземпляр є об’єктом об'єкта в кінці дня. Він збережеться на купі без сумнівів.
RBT

1
@rahulmr Важлива відмінність: конструктор також викликається перед створенням першого (лише AKA) екземпляра.
CoolOppo

53

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

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


1
поліморфізм взагалі не вступає в гру з

32
Так ти думаєш. Я думаю інакше. ;) Наприклад, уявіть однотонну фабрику, яка повертає інтерфейс. Ви знаєте, що ви отримуєте ISingleton (і це той самий назавжди), але необов'язково яку реалізацію.
Моренділ

Вкладений статичний клас може також мати методи екземпляра, його не обмежувати лише статичними методами. Зашифруйте його і ви можете побачити.
nanosoft

У мовах з приємнішою об'єктною моделлю (наприклад, Ruby) класи також є об'єктами. "Суто процедурний" аспект статичного класу - це довільне обмеження, накладене мовою.
Макс

36

У одиночному шаблоні ви можете створити синглтон як екземпляр похідного типу, ви не можете зробити це зі статичним класом.

Короткий приклад:

if( useD3D )
    IRenderer::instance = new D3DRenderer
else
    IRenderer::instance = new OpenGLRenderer

39
Це насправді не однотонний малюнок, мені більше схожий на заводський.
vava

10
Насправді принципова різниця між ними полягає в тому, що Сінглтон буде "кешувати" свій єдиний об'єкт і продовжувати повертати (посилання на) той самий. Фабричний візерунок створить нові екземпляри.
Містик

12
Тоді це проксі-
синглтон

3
Гм, я знаю цей різновид Singleton як MonoState.
Хуппі

Приклад - заводський зразок
Rajavel D

26

Щоб розширити відповідь Джона Скіта

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

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


Я не думаю, що ти можеш прямо знущатися над одинаком. Чи не доведеться вам оголосити інтерфейс, який реалізують однотипний і макетний клас?
Еллен Спертус

@espertus Чому ти не можеш знущатися над одиноким? Приклад з використанням mockito MySingleton mockOfMySingleton = mock(MySingleton.class).
Майк Риландер

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

@espertus Чому ні? Коли ви створюєте екземпляр об'єкта, який ви тестуєте, ви можете замінити реалізацію підкласу синглтона, де б ви не використовували оригінал. Напр .:new ClazzToTest(mockSingleton);
Майк Райландер

Я не використовував Mockito, але як можна підкласирувати клас з приватним конструктором, що стосується одиночних клавіш, за винятком використання рефлексії? Пов'язані дискусії: stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023 / ...
Еллен Spertus

23

Ось хороша стаття: http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-java.html

Статичні класи

  • клас, що має всі статичні методи .
  • краща продуктивність (статичні методи залежать від часу компіляції)
  • не може змінити методи, але може використовувати метод приховування. ( Який метод ховається в Java? Навіть пояснення JavaDoc є заплутаним )

    public class Animal {
        public static void foo() {
            System.out.println("Animal");
        }
    }
    
    public class Cat extends Animal {
        public static void foo() {  // hides Animal.foo()
            System.out.println("Cat");
        }
    }
    

Сінглтон

Підсумовуючи, я б використовував лише статичні класи для проведення утилічних методів, а для Singleton - використання всього іншого.


Правки


4
Я не знаю про java, але в іншому, ваші останні два пункти невірні. Статичні класи можуть посилатися на статичні властивості та поля, тому за станом вони рівні. І вони ліниво завантажені - статичний конструктор запускається, коли: 1) Створюється екземпляр класу. 2) Посилання на будь-якого зі статичних членів класу. 1 не застосовується, що залишає 2. Отже, статичний клас не завантажується до першого використання.
jmoreno

1
Для статичного класу, хоча ви не можете змінити статичний метод, ви можете приховати статичний метод від його батьківського.
Макс Пенг

якщо Animal animal = new Cat();тоді animal.foo();що станеться?
Luminous_Dev

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

@Luminous_Dev: принаймні для .net, статичний клас має конструктор, який запускається при першому зверненні, тому ні, він не доступний миттєво. Статичний конструктор теоретично може зайняти необмежену кількість часу. Там, де він (або будь-який інший клас зберігається) є детальною інформацією про реалізацію, що не дуже відповідає цьому питанню.
jmoreno

22

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


19

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

Коментар Моренділа: "Стиль дизайну, втілений у статичному класі, є суто процедурним". Можливо, я помиляюся, але я не згоден. У статичних методах ви можете отримати доступ до статичних членів, що було б точно так само, як одиночні методи, що мають доступ до членів їхнього єдиного примірника.

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

* або це може бути примірник при першому використанні, я думаю, залежно від мови.


15
Так, всі інші, здається, ігнорують той факт, що клас зі статичними методами також може мати приватні статичні поля, які він все ще може використовувати для підтримання стану (і піддавати деякі з них коду клієнта за допомогою публічних статичних сеттерів / getters).
користувач289463

17

Щоб проілюструвати точку Джона, що показано нижче, неможливо зробити, якщо Logger був статичним класом. Клас SomeClassочікує, що екземпляр ILoggerреалізації буде переданий в його конструктор.

Клас синглтон важливий для можливого введення залежності.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {

            var someClass = new SomeClass(Logger.GetLogger());
        }


    }

    public class SomeClass 
    {
        public SomeClass(ILogger MyLogger)
        {

        }
    }

    public class Logger : ILogger
    {
        private static Logger _logger;
        private Logger() { }

        public static Logger GetLogger()
        {
            if (_logger==null)
            {
                _logger = new Logger();
            }

            return _logger;
        }

        public void Log()
        {

        }

    }


    public interface ILogger
    {
         void Log();
    }
}

13

Ну синглтон - це просто звичайний клас, який ІСНІСТЬ, але лише один раз і опосередковано з клієнтського коду. Статичний клас не є примірником. Наскільки мені відомо, статичні методи (статичний клас повинен мати статичні методи) швидші, ніж нестатичні.

Редагувати:
Опис правила продуктивності FxCop: "Методи, які не отримують доступ до даних екземпляра або методи екземпляра виклику, можуть бути позначені як статичні (Спільне в VB). Після цього компілятор передасть цим членам невіртуальні сайти викликів, що запобіжить перевіряйте під час виконання кожного виклику, який гарантує, що поточний вказівник об'єкта є недійсним. Це може призвести до вимірювання посилення продуктивності для коду, що залежить від продуктивності. У деяких випадках недоступ до поточного екземпляра об'єкта представляє проблему правильності. "
Я насправді не знаю, чи це стосується також статичних методів у статичних класах.


11

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

Статичний клас не може бути примірник іншим, окрім себе.


Статичний клас може бути дуже інстанційним у Java. Прочитайте docs.oracle.com/javase/tutorial/java/javaOO/nested.html. Також дивіться моя відповідь stackoverflow.com/a/37114702/1406510
Nanosoft

8

Основні відмінності:

  • У Singleton є екземпляр / об'єкт, а статичний клас - це купа статичних методів
  • Singleton можна розширити, наприклад, через інтерфейс, тоді як статичний клас не може бути.
  • Singleton може бути успадкований, що підтримує принципи відкриття / закриття в принципах SOLID, з іншого боку статичний клас не може бути успадкований, і нам потрібно внести зміни в себе.
  • Об'єкт Singleton може передаватися методам, тоді як статичний клас, оскільки він не має примірника, не може бути переданий як параметри

7

Синглтон краще підходити з точки зору тестування. На відміну від статичних класів, одиночний може реалізувати інтерфейси, і ви можете використовувати екземпляр макету та вводити їх.

У наведеному нижче прикладі я проілюструю це. Припустимо, у вас є метод isGoodPrice (), який використовує метод getPrice (), а ви реалізуєте getPrice () як метод в одиночному.

синглтон, який забезпечує функцію getPrice:

public class SupportedVersionSingelton {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        // calculate price logic here
        return 0;
    }
}

Використання getPrice:

public class Advisor {

    public boolean isGoodDeal(){

        boolean isGoodDeal = false;
        ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
        int price = supportedVersion.getPrice();

        // logic to determine if price is a good deal.
        if(price < 5){
            isGoodDeal = true;
        }

        return isGoodDeal;
    }
}


In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it. 



  public interface ICalculator {
        int getPrice();
    }

Остаточна реалізація Singleton:

public class SupportedVersionSingelton implements ICalculator {

    private static ICalculator instance = null;

    private SupportedVersionSingelton(){

    }

    public static ICalculator getInstance(){
        if(instance == null){
            instance = new SupportedVersionSingelton();
        }

        return instance;
    }

    @Override
    public int getPrice() {
        return 0;
    }

    // for testing purpose
    public static void setInstance(ICalculator mockObject){
        if(instance != null ){
instance = mockObject;
    }

тестовий клас:

public class TestCalculation {

    class SupportedVersionDouble implements ICalculator{
        @Override
        public int getPrice() { 
            return 1;
        }   
    }
    @Before
    public void setUp() throws Exception {
        ICalculator supportedVersionDouble = new SupportedVersionDouble();
        SupportedVersionSingelton.setInstance(supportedVersionDouble);

    }

    @Test
    public void test() {
          Advisor advidor = new Advisor();
          boolean isGoodDeal = advidor.isGoodDeal();
          Assert.assertEquals(isGoodDeal, true);

    }

}

У випадку, якщо ми застосуємо альтернативу використання статичного методу для реалізації getPrice (), важко було знущатися над getPrice (). Ви можете знущатися над статикою за допомогою енергетичного знущання, але не весь продукт міг би її використовувати.


1
Це зараз не безпечно для потоків, і взагалі неприємно з точки зору того, як ви отримуєте доступ до реалізації інтерфейсу. Звичайно, наявність інтерфейсу приємна для перевірки - але навіщо ж тоді турбуватися з одиночним? Просто уникайте взагалі одинаків; мати один клас, який реалізує його для виробничих цілей, один варіант для тестових цілей, і введіть потрібний екземпляр залежно від того, що ви робите. Зовсім не потрібно зв'язувати одинарного з його абонентами.
Джон Скіт

дякую за відгуки зробити це нитка безпечно дуже просто. крім того, я використовую одиночну для кешування цілей.
Амір Барекет

1
Так, хоча з безглуздими накладними. Знову ж таки, просто не використовувати сингл.
Джон Скіт

6

Я згоден з цим визначенням:

Слово " єдиний " означає один об'єкт протягом життєвого циклу програми, тому область застосування знаходиться на рівні програми.

У статики немає жодного вказівника на об'єкт, тому область застосування знаходиться на рівні домену додатка.

Більше того, обидва повинні бути реалізовані, щоб бути безпечними для потоків.

Ви можете знайти інші цікаві відмінності щодо: Singleton Pattern Versus Static Class


5

Одна помітна відмінність полягає в інстанції, що поставляється з Singletons.

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


4

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

Я б сказав, що найбільша різниця полягає в тому, що синглтон все ще є нормальним Java Bean, а не спеціалізованим статичним Java класом. І через це синглтон приймається в багатьох інших ситуаціях; це насправді стратегія створення екземплярів Spring Framework за замовчуванням. Споживач може, а може і не знати, що сингтон передається навколо, він просто ставиться до цього, як до звичайного Java-боба. Якщо вимога змінюється, а одиночному замість цього потрібно стати прототипом, як ми часто бачимо навесні, це можна зробити абсолютно безперешкодно, без зміни коду для споживача.

Хтось ще раніше згадував, що статичний клас повинен бути суто процедурним, наприклад, java.lang.Math. На мій погляд, такого класу ніколи не можна передавати, і вони ніколи не повинні містити нічого, крім статичного остаточного, як атрибути. Для всього іншого використовуйте синглтон, оскільки він набагато гнучкіший і простіший в обслуговуванні.


4

У нас є база БД, яка встановлює з'єднання з Back end. Щоб уникнути брудних читань для декількох користувачів, ми використовували одиночну схему, щоб гарантувати, що ми маємо доступність одного примірника в будь-який момент часу.

У c # статичний клас не може реалізувати інтерфейс. Коли для одного класу екземплярів потрібно реалізувати інтерфейс для бізнес-контрактів або цілей IoC, саме тут я використовую шаблон Singleton без статичного класу

Сінглтон пропонує спосіб підтримувати стан у сценаріях без громадянства

Сподіваюся, що допоможе вам ..


3
  1. Ледаче завантаження
  2. Підтримка інтерфейсів, щоб забезпечити окрему реалізацію
  3. Можливість повернення похідного типу (як поєднання лінивого завантаження та реалізації інтерфейсу)

Вкладений статичний клас може дуже реалізувати інтерфейс у Java. Ваш другий пункт - Неправильно.
nanosoft

3

а. Серіалізація - Статичні члени належать до класу, а тому не можуть бути серіалізовані.

б. Хоча ми зробили конструктор приватним, змінні статичних членів все одно будуть перенесені до підкласу.

c. Ми не можемо зробити ліниву ініціалізацію, оскільки все буде завантажено лише при завантаженні класу.


3

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


3

Я читаю наступне і думаю, що це теж має сенс:

Турбота про бізнес

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

з книги «Об’єктно-орієнтований думковий процес» 4-е вид.


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

3

У статті, яку я написав, я описав свою точку зору щодо того, чому синглтон набагато кращий, ніж статичний клас:

  1. Статичний клас насправді не є канонічним класом - це простір імен з функціями та змінними
  2. Використання статичного класу не є хорошою практикою через порушення об'єктно-орієнтованих принципів програмування
  3. Статичний клас не можна передавати як параметр для інших
  4. Статичний клас не підходить для "ледачої" ініціалізації
  5. Ініціалізація та використання статичного класу завжди важко відслідковувати
  6. Реалізація управління потоком важко

Я б підніс це для граматики англійської мови, але в іншому випадку це цікаво читати :)
Noctis

3
  1. Ми можемо створити об’єкт однокласного класу і передати його методу.

  2. Клас Singleton не обмежує спадкування.

  3. Ми не можемо розпоряджатись об’єктами статичного класу, але можемо однотонний клас.


У чому полягає користь передачі синглтона в метод, якщо завжди є лише один, і у нього завжди є статична довідка?
Аарон Франке

3

Відмінність від статичного класу

У JDK є приклади як однотонних, так і статичних, з одного боку java.lang.Math- кінцевий клас зі статичними методами, з іншого java.lang.Runtime- клас синглтон.

Переваги одинарного

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

  • Клас Singleton може бути ледачим навантаженням, якщо його важкий предмет, але статичний клас не має таких переваг і завжди охоче завантажується.

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

  • Оскільки статичні методи на Java не можуть бути відмінені, вони призводять до негнучкості. З іншого боку, ви можете змінити методи, визначені в однотонному класі, розширивши його.

Недоліки статичного класу

  • Простіше написати тест одиниці для однотонного, ніж статичний клас, оскільки ти можеш передавати макетний об'єкт, коли очікується одиночний.

Переваги статичного класу

  • Статичний клас забезпечує кращу продуктивність, ніж однотонний, оскільки статичні методи пов'язані на час компіляції.

Існує кілька реалізацій однотонного малюнка, кожен з яких має переваги та недоліки.

  • Швидке завантаження синглів
  • Двічі перевірений блокування синглтон
  • Ідіомія власника ініціалізації на вимогу
  • На основі перерахунку синглтон

Детальний опис кожного з них занадто багатослівний, тому я просто поклав посилання на хорошу статтю - Все, що ви хочете знати про Singleton


2

Існує величезна різниця між одним екземпляром статичного класу (тобто одиничним екземпляром класу, який, як буває, статичною або глобальною змінною), і одним статичним вказівником на екземпляр класу на купі:

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


1
Отож, якщо виходи із програми, Синглтон все ще залишиться в пам'яті?
nanosoft

Я думаю, ти маєш на увазі, коли завершується поточна нитка, а не програма, правда? Якщо програма закривається, інший потік не може використовувати щось із неї.
Том Бріто

2

Різниця в моїй голові полягає в реалізації об'єктно-орієнтованого програмування (Singleton / Prototype) або функціонального програмування (Static).

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

З іншого боку, статика використовується для реалізації функціонального програмування. Статичні члени належать до класу. Вони без громадянства.

До речі, ви знали, що можете створювати одиночні статичні класи :)


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