Подтвердить что ты не робот

Почему существуют классы java singleton? Когда вам нужно будет использовать один

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

Спасибо,

4b9b3361

Ответ 1

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

Зачем использовать синглтоны?

Вы можете использовать "синглтон" Google, чтобы найти всевозможные причины. Из JavaWorld:

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

Зачем использовать Singleton вместо класса со всеми статическими методами?

Несколько причин

  • Вы можете использовать наследование
  • Вы можете использовать интерфейсы
  • Это упрощает выполнение модульного тестирования самого одиночного класса
  • Это позволяет выполнять модульное тестирование кода, зависящего от singleton

Для # 3, если ваш Singleton был пулом подключений к базе данных, вы хотите, чтобы ваше приложение имело только один экземпляр, но выполняйте модульное тестирование пула соединений с базой данных без попадания в базу данных (возможно, с помощью области приложения конструктор или статический метод создания):

public class DatabaseConnectionPool {
  private static class SingletonHolder {
    public static DatabaseConnectionPool instance = new DatabaseConnectionPool(
        new MySqlStatementSupplier());
  }

  private final Supplier<Statement> statementSupplier;

  private DatabaseConnectionPool(Supplier<Statement> statementSupplier) {
    this.statementSupplier = statementSupplier;
  }

  /* Visibile for testing */
  static DatabaseConnectionPool createInstanceForTest(Supplier<Statement> s) {
    return new DatabaseConnectionPool(s);
  }

  public static DatabaseConnectionPool getInstance() {
    return SingletonHolder.instance;
  }

  // more code here
}

(обратите внимание на использование шаблона Инициализация по требованию

Затем вы можете выполнить тестирование DatabaseConnectionPool с помощью метода .

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

Вместо этого вы можете использовать инфраструктуру инъекций зависимостей, такую ​​как Spring или Guice, чтобы гарантировать, что ваш класс имеет только один экземпляр в процессе производства, но все же позволяет использовать код, который использует класс для проверки. Поскольку методы в Singleton не являются статичными, вы можете использовать насмешливую структуру, такую ​​как JMock, чтобы высмеивать ваш синглтон в тестах.

Ответ 2

Класс с только статическими методами (и private contructor) - это вариант, где нет экземпляра вообще (0 экземпляров).

Singleton - это класс, для которого имеется ровно один экземпляр.

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

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

Ответ 3

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

Ответ 4

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

Обычно вы создаете синглтон, например, синхронизируете на getInstance:

public class Singleton {

    private static Singleton instance;

    private Singleton(){
         // create resource here
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }

        return instance;
    }
}

Но одинаково справедливо создавать его так,

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton(){
        // create resource here
    }

    public static Singleton getInstance() {
        return instance;
    }
}

Оба метода создадут одноповерочный загрузчик классов PER.

Ответ 5

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

Ответ 6

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

Например, представьте, что у вас был один провайдер соединений, который создает соединения с БД.

public class DBConnectionProvider implements ConnectionProvider {}

Если бы это был класс со статическими методами, вы не могли бы вводить зависимость, например:

public void doSomeDatabaseAction(ConnectionProvider cp) {
   cp.createConnection().execute("DROP blah;");
}

Это должно быть

public void doSomeDatabaseAction() {
   DBConnectionProvider.createConnection().execute("DROP blah;");
}

Включение зависимостей полезно, если вы позже захотите unit test ваш метод (вместо этого вы можете передать провайдер изделенного соединения).

Ответ 7

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

Ответ 8

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

Что касается использования синхронизации, это определенно дорого, и единственная синхронизация времени актуальна в первый раз или уникальная инстанция после создания экземпляра, мы больше не нуждаемся в синхронизации. После первого раза синхронизация полностью не нужна: (

Ответ 9

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

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

Синглтоны, с другой стороны, являются истинными объектами. В идеале, singleton должен быть реализован без использования одноэлементной модели. Это позволит вам легко переключиться на использование нескольких экземпляров, если вам это вдруг понадобится. Например, у вас может быть только одно соединение с базой данных, но тогда вам придется работать с другой, полностью несвязанной базой данных одновременно. Вы просто превращаете свой синглтон в "двойник" или "триптон" или что-то еще. Если вам нужно, вы также можете сделать его конструктором общедоступным, что позволит создать как можно больше экземпляров. Все эти вещи не так просто реализовать со статическими классами.

Проще говоря, singleton - это обычный класс, который имеет один экземпляр в глобальном масштабе, чтобы избавить вас от всех проблем передачи его везде как параметра.

И нет особых проблем при создании синглета. Вы просто создаете обычный класс с частным конструктором, а затем реализуете один метод factory, и все готово.

Ответ 10

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

Во всех смыслах и целях нет оснований предпочитать односторонний подход к описанному вами подходу. Кто-то решил, что статические переменные являются капиталом-b Плохой (как и другие иногда полезные функции, такие как gotos), потому что они не за горами, и в ответ у нас есть обход одиночных чисел.