Разница между статическим классом и одноэлементным шаблоном?


1769

Какая реальная (то есть практическая) разница существует между статическим классом и одноэлементным шаблоном?

Оба могут быть вызваны без создания экземпляров, оба предоставляют только один «Экземпляр», и ни один из них не является поточно-ориентированным. Есть ли другая разница?


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

ИМО, этот ответ очень хорошо подводит итог. Stackoverflow.com/questions/14097656/…
Дейв

Ответы:


1251

Что заставляет вас говорить, что одноэлементный или статический метод не безопасен для потоков? Обычно оба должны быть реализованы, чтобы быть потокобезопасными.

Большая разница между синглтоном и кучей статических методов заключается в том, что синглтоны могут реализовывать интерфейсы (или получать полезные базовые классы, хотя, по моему опыту, это менее распространено), так что вы можете обойти синглтон, как если бы он был «просто другим». " реализация.


29
Что ж, если вы предпочитаете это, ни один из них не является по сути потокобезопасным, вы должны сделать так, чтобы они оба были поточно-ориентированными, так что никакой разницы нет.
Хорхе Кордова

119
Можете ли вы привести пример чего-то, что по своей сути является потокобезопасным, кроме неизменяемых типов?
Джон Скит

26
To Skeet: Люди, которые говорят, что синглтон не является потокобезопасным, означают, что синглтон неоправданно распределяется между потоками все время, в то время как объекты стека используются совместно, когда вам это нужно, что означает, что вам не нужно выполнять ненужную синхронизацию.

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

10
@AmirBareket: Это не одноэлементный шаблон в соответствии с шаблоном одноэлементного проектирования - если сам класс позволяет создавать несколько экземпляров, это не одноэлементный IMO, независимо от того, что делает фабрика.
Джон Скит

476

Правильный ответ - Джон Скит, на другом форуме здесь .

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

Статический класс допускает только статические методы.


64
Зачем вам передавать параметр Singleton в качестве параметра, если вы можете получить доступ к одному и тому же экземпляру практически из любого места, вызвав статический метод getInstance ()?
Энрике Ордина

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

6
@HenriqueOrdine Они говорят о статическом классе, а не о классе со статическими методами. Статический класс не может быть создан. Тем не менее, если вы передаете экземпляр (нестатического) класса, который содержит статические методы, вы не можете вызывать статические методы для экземпляра.
Горан

3
Что такое статический класс? По крайней мере, в Java такого нет.
Энрике Ордина

16
@ Goran Я был изначально очень смущен вашей формулировкой. Вы сказали: «Вы не можете вызывать статические методы в экземпляре». Я читал это как «если у вас есть ссылка на экземпляр объекта, вы не можете вызвать какие-либо статические методы, которые он может иметь». Это, конечно, неправильно. Прочитав его несколько раз, я думаю, что вы имели в виду «внутри статических методов вы не можете получить доступ к нестатическим объектам в классе», что является правильным. Хочу уточнить, что для тех, кто плохо знаком с этими понятиями, кто сталкивается с этим ответом и читает ваши комментарии.
Эндрю Штайц

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

100
Второе утверждение неверно. Мы не можем клонировать объект Singleton. Реализация Singleton должна отказаться от этого. Если вы действительно можете клонировать Синглтон, это не Синглтон.
Александр Янчарук

19
Это неверный ответ для Java: ни синглтон, ни статика не используют стек.
AgilePro

72
# 1 не важно. № 2 описывает дефектную реализацию. № 3 совершенно неоправдан.
Кейси

31
Как статический объект может храниться в стеке? Новый кадр стека создается при вызове метода, в нем хранятся локальные переменные метода, этот кадр стека удаляется при возврате метода, и эти локальные переменные теряются. Конечно, стек быстрый, но он не подходит для хранения статических объектов.
mike_m

23
Я не могу понять количество голосов против этого. 1) Почему Singleton должен храниться в стеке? В управляемых языках, таких как C # или Java, данные хранятся в управляемой куче, за исключением локальных переменных / параметров метода. 2) Если вы можете клонировать его, то это не правильно реализованный синглтон. 3) Синглтон известен как анти-паттерн ООП; то, что вы должны избегать, если это возможно. 4) Это единственное, что правильно.
Groo

152

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


10
+1 за хорошие, прагматичные баллы. Шаблон синглтона в общем случае чрезмерно используется, но есть несколько ситуаций, когда он подходит. Смотрите также: agiletribe.wordpress.com/2013/10/08/…
AgilePro

3
Вы правы в том, что вы полиморфны. Это самый важный момент
Ахмад

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

75

staticзанятия не для чего то нужного государства. Это полезно для объединения нескольких функций, т.е. Math(или Utilsв проектах). Таким образом, имя класса просто дает нам подсказку, где мы можем найти функции и ничего более.

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

Мое правило выбора между staticиsingleton :

Если есть множество функций, которые должны храниться вместе, то staticэто выбор. Все, что требует единого доступа к некоторым ресурсам, может быть реализовано как singleton.


16
Почему статические классы не должны делать ничего, что должно сохранять состояние?
Trisped

12
@Trisped: У вас нет точного контроля над инициализацией или финализацией.
Xaqron

7
Вы потеряли меня в «Синглтоне - мой любимый образец». Синглтон - такой острый угол, что его следует рассматривать как анти-паттерн, так и паттерн. Классы могут иметь статические состояния, это также единый доступ, если любое статическое состояние является более «единичным доступом», чем одиночные, потому что большинство реализаций синглтона нарушены, т.е. вы можете клонировать синглтон, в то время как статическое определение определено как уникальное.
PoweredByRice

1
Что значит поддерживать состояние? Что такое государство?
Кайл Делани

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

65

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

  1. Вы не можете создать экземпляр статического класса.

  2. Загружается автоматически общеязыковой средой .NET Framework (CLR) при загрузке программы или пространства имен, содержащих класс.

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

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

  5. Мы не можем наследовать статический класс другому статическому классу в C #.

  6. Класс, имеющий все статические методы.

  7. Лучшая производительность (статические методы связаны во время компиляции)

Singleton: -

  1. Вы можете создать один экземпляр объекта и использовать его повторно.

  2. Экземпляр Singleton создается впервые по запросу пользователя.

  3. Класс Singleton может иметь конструктор.

  4. Вы можете создать объект синглтон-класса и передать его методу.

  5. Класс Singleton не говорит о каких-либо ограничениях наследования.

  6. Мы можем располагать объекты одноэлементного класса, но не статического класса.

  7. Методы могут быть переопределены.

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

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


13
Статические классы имеют конструкторы: msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
Томер Арази,

2
Да, у static может быть конструктор, который является внутренним для этого класса. Это вызывается, когда вызывается любой статический метод в классе.
17

Для синглтона во время компиляции он сохраняется в памяти HEAP, но если он создается один раз, сохраняется ли он в STACK?
Luminous_Dev

@Luminous_Dev Нет. Любой одноэлементный экземпляр является экземпляром объекта в конце дня. Он будет храниться в куче без сомнения.
RBT

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

53

Статический класс - это класс, в котором есть только статические методы, для которых более подходящим словом будут «функции». Стиль дизайна, воплощенный в статическом классе, является чисто процедурным.

Синглтон, с другой стороны, является паттерном, характерным для ОО-дизайна. Это экземпляр объекта (со всеми присущими ему возможностями, такими как полиморфизм), с процедурой создания, которая гарантирует, что в течение всего времени существования существует только один экземпляр этой конкретной роли.


1
полиморфизм вообще не вступает в игру с одиночками

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

Вложенный статический класс также может иметь методы экземпляра, не ограничиваясь только статическими методами. Кодируйте его, и вы увидите.
нанософт

В языках с более красивой объектной моделью (например, Ruby) классы также являются объектами. «Чисто процедурный» аспект статического класса - это произвольное ограничение, налагаемое языком.
Макс

36

В шаблоне синглтона вы можете создать синглтон как экземпляр производного типа, вы не можете сделать это со статическим классом.

Быстрый пример:

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

39
Это на самом деле не одноэлементная модель, для меня это больше похоже на фабрику.
Вава

10
Не совсем, фундаментальное различие между ними состоит в том, что Singleton будет «кэшировать» свой единственный объект и продолжать возвращать (ссылку на) один и тот же объект. Шаблон Factory создаст новые экземпляры.
Мистик

12
Тогда это прокси-синглтон :)
vava

3
Хм, я знаю эту разновидность Синглтона как MonoState.
Huppie

пример - фабричный образец
Раджавель Д

26

Расширить ответ Джона Скита

Большая разница между одноэлементным и кучей статических методов заключается в том, что синглтоны могут реализовывать интерфейсы (или наследовать полезные базовые классы, хотя это не так часто встречается в IME), поэтому вы можете передавать одиночный код, как если бы это была «просто другая» реализация.

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


Я не думаю, что вы можете напрямую издеваться над синглтоном. Разве вам не нужно объявлять интерфейс, который реализуют и синглтон, и класс mock?
Эллен Спертус

@espertus Почему ты не смеешься над своим синглтоном? Пример использования mockito MySingleton mockOfMySingleton = mock(MySingleton.class).
Майк Райландер,

Вы правы, вы можете издеваться над ним с помощью таких инструментов, как mockito, которые используют отражение. Я имел в виду, что вы не можете издеваться над ним напрямую, подклассифицируя его и переопределяя его методы.
Эллен Спертус

@espertus Почему бы и нет? Когда вы создаете экземпляр тестируемого объекта, вы можете заменить реализацию подкласса вашего синглтона, где бы вы ни использовали оригинал. Пример:new ClazzToTest(mockSingleton);
Майк Райландер

Я не использовал Mockito, но как вы можете создать подкласс для класса с закрытым конструктором, как в случае синглетонов, за исключением использования отражения? Связанные обсуждения: stackoverflow.com/questions/2302179/mocking-a-singleton-class stackoverflow.com/questions/15939023/…
Эллен Спертус,

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");
        }
    }
    

одиночка

Таким образом, я бы использовал статические классы только для хранения утилит, а для всего остального - синглтон.


Правки


4
Я не знаю о Java, но в .Net, ваши последние два пункта неверны. Статические классы могут ссылаться на статические свойства и поля, поэтому по состоянию они равны. И они загружаются лениво - статический конструктор запускается, когда: 1) Создается экземпляр класса. 2) Ссылка на любой из статических членов класса. 1 не применяется, что оставляет 2. Таким образом, статический класс не загружается до первого использования.
Jmoreno

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

если Animal animal = new Cat();тогда animal.foo();что происходит?
Luminous_Dev

@jmoreno статический класс не загружается до первого использования? Я считаю, что он хранится в памяти стека во время компиляции. И к нему мгновенно получают доступ .. не так ли?
Luminous_Dev

@Luminous_Dev: по крайней мере для .net, статический класс имеет конструктор, который запускается при первом обращении, поэтому он не доступен мгновенно. Статический конструктор может теоретически занимать неограниченное количество времени. Где он (или любой другой класс хранится) является деталью реализации, которая на самом деле не имеет отношения к этому вопросу.
Jmoreno

22

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


19

Я не большой теоретик ОО, но из того, что я знаю, я думаю, что единственная особенность ОО, которой нет в статических классах по сравнению с синглетонами, это полиморфизм. Но если вам это не нужно, со статическим классом вы, конечно, можете иметь наследование (не уверенное в реализации интерфейса) и инкапсуляцию данных и функций.

Комментарий Морендила: «Стиль дизайна, воплощенный в статическом классе, является чисто процедурным» Я могу ошибаться, но я не согласен. В статических методах вы можете получить доступ к статическим элементам, которые будут точно такими же, как одноэлементные методы для доступа к их отдельным элементам экземпляра.

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

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


15
Да, все остальные, кажется, игнорируют тот факт, что класс со статическими методами может также иметь частные статические поля, которые он все еще может использовать для поддержания состояния (и предоставлять некоторые из них клиентскому коду через общедоступные статические установщики / получатели).
user289463

17

Чтобы проиллюстрировать точку зрения Джона, то, что показано ниже, невозможно, если Logger был статическим классом. Класс SomeClassожидает, что экземпляр ILoggerреализации будет передан в его конструктор.

Класс Singleton важен для внедрения зависимости.

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: «Методы, которые не обращаются к данным экземпляра или методы экземпляра вызова, могут быть помечены как статические (Shared в VB). После этого компилятор будет генерировать не виртуальные сайты вызовов для этих членов, что предотвратит проверка во время выполнения для каждого вызова, который гарантирует, что текущий указатель объекта не равен нулю. Это может привести к ощутимому приросту производительности для чувствительного к производительности кода. В некоторых случаях невозможность доступа к текущему экземпляру объекта представляет проблему правильности ».
Я на самом деле не знаю, относится ли это также к статическим методам в статических классах.


11

Одиночные экземпляры создаются, просто существует только один экземпляр, следовательно, единственный в Синглтоне.

Статический класс не может быть создан чем-либо, кроме самого себя.


Статический класс может быть очень сильно создан в Java. Прочитайте docs.oracle.com/javase/tutorial/java/javaOO/nested.html. Также см. Мой ответ stackoverflow.com/a/37114702/1406510
nanosoft

8

Основные отличия:

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

7

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

В приведенном ниже примере я проиллюстрирую это. Предположим, у вас есть метод 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 и статический класс


5

Одним заметным отличием является различная реализация, которая идет с синглетонами.

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


4

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

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

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


4

У нас есть база БД, которая устанавливает соединения с Back-end. Чтобы избежать грязного чтения среди нескольких пользователей, мы использовали одноэлементный шаблон, чтобы обеспечить доступность одного экземпляра в любой момент времени.

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

Синглтон обеспечивает способ поддерживать состояние в сценариях без сохранения состояния

Надеюсь, что это поможет вам ..


4

Отличие от статического класса

В JDK есть примеры как singleton, так и static, с одной стороны java.lang.Math, это финальный класс со статическими методами, с другойjava.lang.Runtime - синглтон-класс.

Преимущества синглтона

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

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

  • С помощью singleton вы можете использовать наследование и полиморфизм для расширения базового класса, реализации интерфейса и предоставления различных реализаций.

  • Поскольку статические методы в Java не могут быть переопределены, они ведут к негибкости. С другой стороны, вы можете переопределить методы, определенные в одноэлементном классе, расширив его.

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

  • Легче написать модульный тест для синглтона, чем статический класс, потому что вы можете передать фиктивный объект, когда ожидается синглтон.

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

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

Существует несколько реализаций синглтон-паттернов, каждый из которых имеет свои преимущества и недостатки.

  • Стремительная загрузка синглтона
  • Двойная проверка блокировки синглтона
  • Идиома держателя инициализации по требованию
  • Синглтон на основе перечисления

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


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

Вложенный статический класс может очень реализовать интерфейс в Java. Ваш второй пункт неверен.
нанософт

3

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

б. Хотя мы сделали конструктор закрытым, статические переменные-члены все равно будут перенесены в подкласс.

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


3

С точки зрения клиента, статическое поведение известно клиенту, но поведение Singleton может быть скрыто от клиента. Клиент может никогда не узнать, что есть только один экземпляр, с которым он играет снова и снова.


3

Я прочитал следующее и думаю, что это тоже имеет смысл:

Забота о бизнесе

Помните, одно из самых важных правил ОО состоит в том, что объект отвечает за себя. Это означает, что вопросы, касающиеся жизненного цикла класса, должны обрабатываться в классе, а не делегироваться таким языковым конструкциям, как static и т. Д.

из книги «Объектно-ориентированный мыслительный процесс», 4-е изд.


Я бы не согласился, так как это действительно добавляет ответственности к классу, что (если он что-то делает) означает, что теперь он нарушает принцип единой ответственности.
ssmith

3

В статье, которую я написал, я описал свою точку зрения о том, почему синглтон намного лучше, чем статический класс:

  1. Статический класс на самом деле не канонический класс - это пространство имен с функциями и переменными
  2. Использование статического класса не является хорошей практикой из-за нарушения принципов объектно-ориентированного программирования
  3. Статический класс не может быть передан в качестве параметра для других
  4. Статический класс не подходит для «ленивой» инициализации
  5. Инициализация и использование статического класса всегда отслеживаются
  6. Реализовать управление потоками сложно

Я хотел бы освежить это для грамматики английского языка, но в остальном, это интересное чтение :)
Noctis

3
  1. Мы можем создать объект синглтон-класса и передать его методу.

  2. Класс Singleton не ограничивает наследование.

  3. Мы не можем распоряжаться объектами статического класса, но можем использовать одноэлементный класс.


Какая польза от передачи синглтона в метод, если всегда есть только один, и у этого всегда есть статическая ссылка?
Аарон Франке

2

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

Когда ваше приложение завершается, вызывается деструктор экземпляра статического класса. Это означает, что если вы использовали этот статический экземпляр как синглтон, ваш синглтон перестал работать правильно. Если все еще выполняется код, который использует этот синглтон, например, в другом потоке, этот код, скорее всего, потерпит крах.


1
Так что, если приложение выйдет из системы, останется ли Singleton в памяти?
Нанософт

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

2

Разница в моей голове заключается в реализации объектно-ориентированного программирования (Singleton / Prototype) или функционального программирования (Static).

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

С другой стороны, static используется для реализации функционального программирования. Статические члены принадлежат классу. Они без гражданства.

Кстати, вы знали, что можете создавать одноэлементные статические классы :)


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