Почему люди используют синглтоны в своей структуре PHP

Хорошо, ребята, я изо всех сил пытаюсь понять, зачем нужна синглтон.

Сделайте реальный пример: у меня есть структура для моей CMS
Мне нужен класс, который регистрирует некоторую информацию (пусть наклеивается на PHP).

Пример:

class Logger{
   private $logs = array();

   public function add($log) {
      $this->logs[]=$log;
   }      
}

Теперь, конечно, этот вспомогательный объект должен быть уникальным для срока службы запроса страницы моей CMS.
И чтобы решить это, мы сделали бы его singleton (объявив private конструктором и т.д.)

Но почему, черт возьми, такой класс не слишком статичен? Это решило бы потребность в одноэлементном шаблоне (который считался плохим параметром). Пример:

class Logger {
    private static $logs = array();

    public static function add($log) {
        self::$logs[]=$log;
    }
}

Сделав этот помощник полностью статическим, когда нам нужно добавить журнал где-нибудь в нашем приложении, нам просто нужно называть его статически, как: Logger::add('log 1'); vs oneton call like: Logger::getInstance()->add('log 1');

Надеюсь, что кто-то упростит для меня понимание, почему использует singleton над статическим классом в PHP.

Изменить

Это довольно приятная лекция о синглете против статического класса, для кого это интересно, благодаря @James. (Обратите внимание, что это не касается моего вопроса)

Ответ 1

По многим причинам.

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

Поскольку у вас не может быть метода __construct, вам, возможно, придется поместить статический метод init где-нибудь. Теперь люди в своем коде не уверены, был ли метод init ранее вызван. Повторяют ли они это? Нужно ли им искать код для этого звонка? Что, если init был где-то, но потом удаляется или ломается? Многие места в вашем коде теперь полагаются на место, которое вызывает метод init.

Статические методы, как известно, трудно unit test со многими модулями модульного тестирования.

Есть много причин, но их сложно перечислить.

Синглтоны действительно не нужны, если вы используете DI.

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

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

Ответ 2

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

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

Тем не менее, эти два дополняют друг друга: статическая функция может быть использована для возврата одного элемента в один класс. То, что я делаю в singleton, я использую чаще всего: обработчик базы данных.

Теперь многим программистам говорят, что "одиночные игры плохие, мм'кай"? но не замечают гонщика, что такие вещи, как обычно, являются плохими при злоупотреблении. Как мастер-резчик, опытный программист располагает множеством инструментов, и многие из них не будут пользоваться большим спросом. Мой обработчик базы данных идеален как одноэлементный, но это только, который я обычно использую. Для класса журнала я обычно использую статические методы.

Ответ 3

Синглеты позволяют вам переопределить поведение. Logger:: add ('1'), например, может регистрироваться на разных устройствах, только если класс Logger знает, как это сделать. Logger:: getLogger() → add ('1') может делать разные вещи в зависимости от того, какой подтип Logger getLogger() возвращается. Конечно, вы можете делать все в рамках класса logger, но часто вы в конечном итоге реализуете singleton внутри статического класса.

Ответ 4

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

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

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

UPDATE:

Это может быть полезно, сравнение по статическому или singleton в PHP.

http://moisadoru.wordpress.com/2010/03/02/static-call-versus-singleton-call-in-php/

Ответ 5

Как упоминалось в leblonk, вы не можете переопределять статические классы, что очень затрудняет модульное тестирование. С помощью singleton вы можете создать экземпляр объекта "mock" вместо фактического класса. Никаких изменений кода не требуется.

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

Я часто смешиваю одиночные и статические. Например, я использую класс базы данных, который обеспечивает только 1 подключение к каждому ведущему (статическому) и подчиненному (singleton). Каждый экземпляр класса db может подключаться к другому подчиненному устройству, если запрашивается соединение с тем же подчиненным, возвращается объект singleton. Мастер-соединение - это статический объект, созданный внутри каждого ведомого singleton, поэтому только одно главное соединение существует во всех объектах, созданных db.