Почему люди используют синглтоны в своей структуре 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. (Обратите внимание, что это не касается моего вопроса)

Много причин.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ОБНОВИТЬ:

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

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

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

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

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