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

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

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

44 ответа

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Singleton:-

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Вот хорошая статья: 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 для всего остального.


Правки

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

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

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

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

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

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

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

Чтобы проиллюстрировать точку зрения Джона, то, что показано ниже, невозможно, если 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();
    }
}

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

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

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

Редактировать:
Описание правила производительности FxCop: "Методы, которые не обращаются к данным экземпляра или к методам экземпляра вызова, могут быть помечены как статические (Shared в VB). После этого компилятор будет выдавать не виртуальные сайты вызовов этим членам, что предотвратит проверку на время выполнения для каждого вызова, который гарантирует, что текущий указатель объекта не равен нулю. Это может привести к ощутимому выигрышу в производительности для чувствительного к производительности кода. В некоторых случаях невозможность доступа к текущему экземпляру объекта представляет проблему правильности ".
Я на самом деле не знаю, относится ли это также к статическим методам в статических классах.

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

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

Преимущества singleton

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

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

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

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

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

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

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

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

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

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

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

Синглтон - лучший подход с точки зрения тестирования. В отличие от статических классов, 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(). Вы можете издеваться над статическим электричеством, но не все продукты могут его использовать.

Я согласен с этим определением:

Слово "один" означает один объект в жизненном цикле приложения, поэтому область действия находится на уровне приложения.

Статика не имеет указателя объекта, поэтому область действия находится на уровне домена приложения.

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

Вы можете найти интересные другие отличия о: шаблон Singleton и статический класс

Ниже приведены некоторые основные различия между статическим классом и синглтоном:

1.Singleton — это шаблон, а не ключевое слово, как static. Таким образом, для создания статического класса достаточно ключевого слова static, а в случае синглтона необходимо написать логику для синглтона.

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

3. Статический класс не создается и не расширяется, в отличие от одноэлементного класса.

4. Статический класс запечатывается неявно, но одноэлементный класс должен быть оформлен как запечатанный явно.

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

6. Мы не можем реализовать внедрение зависимостей со статическим классом, но DI возможен с одноэлементным классом, потому что он может управляться интерфейсом. Область действия статического класса находится на уровне домена приложения, поскольку им управляет среда CLR, а область действия одноэлементного объекта охватывает жизненный цикл приложения.

7. Статический класс не может иметь никакого деструктора, но одноэлементный класс может определять деструктор.

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

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

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

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

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

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

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

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

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

Singleton предоставляет возможность поддерживать состояние в сценариях без сохранения состояния

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

  • Класс Singleton предоставляет объект (только один экземпляр) во время жизненного цикла приложения, например java.lang.Runtime

    Хотя статический класс предоставляет только статические методы, такие как java.lang.Math

  • Статические методы в Java нельзя переопределить, но методы, определенные в классе Singleton, можно переопределить, расширив его.

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

Например: java.lang.Runtime, это класс Singleton в Java, вызов getRuntime() Метод возвращает объект среды выполнения, связанный с текущим приложением Java, но обеспечивает только один экземпляр для каждой JVM.

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

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

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

Класс Singleton - это шаблон в объектно-ориентированном дизайне. У класса Singleton есть только один экземпляр объекта в JVM. Этот шаблон реализован таким образом, что в JVM всегда присутствует только один экземпляр этого класса.

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

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

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

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

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

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

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

Другие вопросы по тегам