Есть ли вариант использования синглтонов с доступом к базе данных в PHP?

139

Я получаю доступ к своей базе данных MySQL через PDO. Я настраиваю доступ к базе данных, и моей первой попыткой было использовать следующее:

Первое, о чем я подумал global:

$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');

function some_function() {
    global $db;
    $db->query('...');
}

Это считается плохой практикой. После небольшого поиска я остановился на шаблоне Singleton , который

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

Согласно примеру в руководстве, мы должны сделать это:

class Database {
    private static $instance, $db;

    private function __construct(){}

    static function singleton() {
        if(!isset(self::$instance))
            self::$instance = new __CLASS__;

        return self:$instance;
    }

    function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')

        return self::$db;
    }
}

function some_function() {
    $db = Database::singleton();
    $db->get()->query('...');
}

some_function();

Зачем мне нужен этот относительно большой класс, если я могу это сделать?

class Database {
    private static $db;

    private function __construct(){}

    static function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');

        return self::$db;
    }
}

function some_function() {
    Database::get()->query('...');
}

some_function();

Последний работает отлично, и мне больше не о чем беспокоиться $db.

Как я могу создать меньший одноэлементный класс, или есть вариант использования для синглтонов, который мне не хватает в PHP?

серьезный дев
источник
Есть много ресурсов и дискуссий по этому связанному с этим вопросу: «Что такого плохого в синглтонах?»
FruitBreak

Ответы:

81

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

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

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

Вторая проблема - это тестирование (и, честно говоря, это то же самое, что и первая проблема). Иногда вы хотите заменить свою базу данных фиктивной. Фактически это второй экземпляр объекта базы данных. Это намного сложнее сделать со статическими классами, чем с синглтоном, вам нужно только имитировать метод getInstance (), а не каждый отдельный метод в статическом классе (что на некоторых языках может быть очень сложным).

На самом деле все сводится к привычкам - и когда люди говорят, что «глобалы» - это плохо, у них есть очень веские причины так говорить, но это не всегда будет очевидно, пока вы сами не решите проблему.

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

Билл К
источник
15
Вы говорите, что синглтоны хорошо деградируют до DI, но разве не ваш пример по- getInstance(databaseName)прежнему просто разбрасывает ссылки на глобальный репозиторий экземпляров по всему вашему коду? Код, который будет вызывать, getInstanceдолжен иметь экземпляры, введенные в него клиентским кодом, и поэтому не должен вызывать getInstanceв первую очередь.
Will Vousden 04
1
@Will Vousden Правильно, это своего рода временная остановка. Это не совсем DI, но может быть довольно близко. Например, что, если бы это был getInstance (supportedDatabase), а возвращаемый экземпляр был рассчитан на основе того, какая база данных была передана? Дело в том, чтобы не пугать людей фреймворком DI, пока они к нему не будут готовы.
Bill K
322

Синглтоны очень мало, если не сказать «нет», используются в PHP.

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

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

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

См. Мои слайды о синглтонах в PHP - почему они плохи и как вы можете удалить их из своих приложений для получения дополнительной информации.

Даже Эрих Гамма , один из изобретателей паттерна Синглтон, в наши дни сомневается в этом паттерне:

«Я за то, чтобы отказаться от синглтона. Его использование - почти всегда дизайнерский запах»

дальнейшее чтение

Если после вышесказанного вам все еще нужна помощь в принятии решения:

Диаграмма принятия решений Singleton

Гордон
источник
1
@ Гордон, да. И даже если бы было возможно поддерживать объекты между запросами, синглтоны по-прежнему нарушают пару принципов SOLID и вводят глобальное состояние.
Gordon
4
Извините, что иду против потока, но DI на самом деле не является решением проблемы, для которой используется Singleton, если вы не довольны наличием классов с 42 параметрами ctor (или 42 вызовами setFoo () и setBar (), необходимыми для этого Работа). Да, некоторые приложения, к сожалению, должны быть связаны между собой и зависят от множества внешних факторов. PHP - это язык склеивания, и иногда нужно склеить много вещей.
StasM 05
14
@StasM, если у вас 42 параметра ctor или вам нужно много сеттеров, вы делаете это неправильно. Посмотрите, пожалуйста, беседы о чистом коде. Извините, если я не удосужусь объяснить это еще раз. Не стесняйтесь спрашивать в чате PHP для получения дополнительной информации.
Гордон
21

Кому нужны синглтоны в PHP?

Обратите внимание, что почти все возражения против синглтонов исходят из технических точек зрения, но они также ОЧЕНЬ ограничены по своему объему. Специально для PHP. Сначала я перечислю некоторые причины использования синглтонов, а затем проанализирую возражения против использования синглтонов. Во-первых, люди, которым они нужны:

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

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

- Люди, которым необходимо работать со сторонними API , сервисами и веб-сайтами.

Если вы присмотритесь, это не слишком отличается от предыдущего случая - сторонние API, службы, веб-сайты похожи на внешние изолированные кодовые базы, над которыми у вас нет контроля. Все может случиться. Таким образом, с помощью одноэлементного сеанса / пользовательского класса вы можете управлять ЛЮБОЙ реализацией сеанса / авторизации от сторонних поставщиков, таких как OpenID , Facebook , Twitter и многих других, и вы можете делать это ВСЕ одновременно из ОДНОГО одноэлементного объекта - который легко доступен в известном состоянии в любой момент любого кода, в который вы его вставляете. Вы даже можете создать несколько сеансов для нескольких различных сторонних API / сервисов для одного и того же пользователя на вашем собственном веб-сайте / в приложении и делать с ними все, что хотите.

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

- Люди, которым нужно заниматься быстрым развитием

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

Вы уловили идею. Теперь перейдем к возражениям против одиночек и нечестивому крестовому походу против чего-то полезного :

- Главное возражение состоит в том, что это затрудняет тестирование.

И действительно, до некоторой степени это так, даже если это можно легко смягчить, приняв надлежащие меры предосторожности и закодировав процедуры отладки в свои синглтоны С осознанием того, что вы будете отлаживать синглтон. Но видите ли, это не слишком отличается от ЛЮБОЙ другой философии / метода / шаблона кодирования, которые существуют - просто синглтоны относительно новы и не получили широкого распространения, поэтому текущие методы тестирования оказываются с ними сравнительно несовместимыми. Но это не отличается ни от одного аспекта языков программирования - разные стили требуют разных подходов.

Одно это возражение не соответствует действительности, поскольку оно игнорирует тот факт, что приложения разрабатываются не для «тестирования», и тестирование - не единственный этап / процесс, который входит в разработку приложения. Приложения разработаны для производственного использования. И, как я объяснил в разделе «Кому нужны синглтоны», синглтоны могут заключить ОТЛИЧНУЮ сделку из-за сложности необходимости заставить код работать ВНУТРИ и ВНУТРИ многих различных баз кода / приложений / сторонних сервисов. Время, которое может быть потеряно при тестировании, - это время, потраченное на разработку и развертывание. Это особенно полезно в эпоху сторонней аутентификации / приложений / интеграции - Facebook, Twitter, OpenID и многих других, и неизвестно, что будет дальше.

Хотя это и понятно - программисты работают в самых разных условиях в зависимости от карьеры. И для людей, которые работают в относительно больших компаниях с определенными отделами, занимающимися различным, определенным программным обеспечением / приложениями в удобной манере и без неминуемой гибели сокращения бюджета / увольнений и связанной с этим необходимости делать МНОГО вещей с большим количеством разных вещей в дешевый / быстрый / надежный способ, синглтоны могут показаться не столь необходимыми. И это может даже быть помехой / помехой тому, что у них УЖЕ есть.

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

- Еще одно возражение заключается в том, что объем памяти у него выше.

Поскольку для каждого запроса от каждого клиента будет существовать новый синглтон, это МОЖЕТ быть возражением для PHP. Из-за плохо сконструированных и используемых синглтонов объем памяти приложения может быть выше, если приложение обслуживает много пользователей в любой момент.

Хотя это справедливо для ЛЮБОГО подхода, который вы можете использовать при кодировании. Следует задать следующие вопросы: являются ли методы и данные, которые хранятся и обрабатываются этими синглтонами, ненужными? Ибо, если они НЕОБХОДИМЫ для многих запросов, которые получает приложение, то даже если вы не используете синглтоны, эти методы и данные БУДУТ присутствовать в вашем приложении в той или иной форме через код. Таким образом, все становится вопросом о том, сколько памяти вы будете экономить, когда вы инициализируете традиционный объект класса 1/3 в обработке кода и уничтожаете его на 3/4 в нем.

Видите ли, если поставить такой вопрос, вопрос становится совершенно неактуальным - в вашем коде не должно быть ненужных методов, данных, содержащихся в объектах, в любом случае - независимо от того, используете вы синглтоны или нет. Итак, это возражение против синглтонов становится действительно забавным в том смысле, что оно ПРЕДПОЛАГАЕТ, что будут ненужные методы, данные в объектах, созданных из классов, которые вы используете.

- Некоторые недействительные возражения, такие как «делает невозможным / сложным поддержание нескольких подключений к базе данных»

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

Представьте, что ниже находится внутри синглтона данной базы данных:

$ this -> соединения = массив (); (неправильный синтаксис, я просто набрал его вот так, чтобы дать вам представление - правильное объявление переменной - public $ connections = array (); естественно, используется $ this-> connections ['connectionkey'])

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

$ this -> query (QUERYSTRING, 'queryname', $ this-> connections ['specificulrconnection']);

Который может просто выполнить запрос к выбранной базе данных с выбранным соединением и просто сохранить в вашем

$ this -> результаты

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

Это позволяет поддерживать практически бесконечное количество (в той мере, в которой, конечно, позволяют ограничения ресурсов) различных соединений с базой данных и наборов результатов, сколько вам нужно. И они доступны для ЛЮБОГО фрагмента кода в любой заданной точке любой данной кодовой базы, в которой был создан этот одноэлементный класс.

КОНЕЧНО, вам, естественно, потребуется освободить наборы результатов и соединения, когда они не нужны, но это само собой разумеется, и это не относится к синглтонам или любому другому методу / стилю / концепции кодирования.

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

Короче говоря, в конце концов, одноэлементные шаблоны - это просто еще один метод / стиль / философия для программирования, и они так же полезны, как и ЛЮБЫЕ другие, когда они используются в правильном месте и правильным образом. Что ни от чего не отличается.

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

Посмотрим правде в глаза - все, что не используется должным образом, неправильно, неправильно, ЯВЛЯЕТСЯ злом. Это не ограничивается каким-либо языком, любой концепцией кодирования, любым методом. Всякий раз, когда вы видите, что кто-то делает общие заявления вроде «Х - зло», бегите от этой статьи. Очень высоки шансы, что это продукт ограниченной точки зрения - даже если точка зрения является результатом многолетнего опыта в чем-то конкретном, - что, как правило, в конечном итоге является результатом слишком много работы в определенном стиле / методе - типичный интеллектуальный консерватизм.

Для этого можно привести бесконечное количество примеров, начиная от «глобальные объекты - зло» до «iframe - это зло». Примерно 10 лет назад даже предложение использовать iframe в любом приложении было ересью. Затем идет Facebook, везде фреймы, и посмотрите, что произошло - фреймы больше не такие уж злые.

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

Главный актив программиста / кодировщика / программиста - это свободный, открытый и гибкий ум.

unity100
источник
2
-1. Хотя я согласен с тем, что открытый и гибкий ум является обязательным активом для любого разработчика, это не исключает синглтона из антипаттерна. Приведенный выше ответ содержит так много неточных утверждений и неправильных выводов о природе и влиянии синглтона, что я не могу не проголосовать за него.
Гордон
-1. Мне пришлось испытать фреймворк с множеством синглтонов на собственном опыте, и автоматическое тестирование невозможно. Мне нужно вручную все проверить методом проб и ошибок в браузере. Некоторые ошибки можно предотвратить с помощью проверки кода (орфографические, синтаксические ошибки), но функциональные ошибки часто скрыты. Это тестирование требует намного больше времени, чем модульные тесты. С модульными тестами я мог бы сказать: этот класс работает изолированно, ошибка должна быть где-то еще. Без отладки утомительно.
Джим Мартенс,
Фреймворк должен был иметь встроенные средства ведения журнала и отслеживания ошибок. Кроме того, класс, работающий правильно изолированно, также будет правильно работать в одноэлементной форме при включении в более широкое приложение. Это означает, что в этом случае нарушается другой класс или функция, взаимодействующая с этим синглтоном. Это ничем не отличается от обычного отслеживания ошибок внутри большого приложения. Что само по себе довольно сложно без надлежащего ведения журнала приложения.
unity100
Неточно. Тонны синглтонов определенно ЗЛО, потому что они создают Testing-HELL. :-) Тем не менее, один синглетон на приложение может быть хорошим. Например: как единая функция ведения журнала - для реализации во всех приложениях (включая некоторые из них с устаревшим кодом).
Филип Обертон, певец Ридло,
«Время, которое можно потерять на тестирование ...» Это действительно плохая практика и образ мышления. Все эти устаревшие приложения были разработаны с учетом этого, и их стало невозможно поддерживать, поэтому их нужно было переписать. Если тестов нет, время будет потеряно, когда новая функция будет разработана и что-то сломает в какой-то другой части системы. Время, потерянное на отладку, время, потерянное пользователями, которые могут использовать эту функцию должным образом, потеря уверенности в приложении и т. Д.
bogdancep
15

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

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

Уилл Вусден
источник
Но синглтоны могут очень плавно превращаться в DI, а статические классы - нет, что является настоящей проблемой для статических классов.
Bill K
@ Билл: Совершенно верно, но тогда я бы предпочел для начала подход DI, а не
отдельные
В некоторых языках (например, Java) статические классы (или статические методы классов) не могут быть расширены. Таким образом, вы создаете потенциальные проблемы (или, в лучшем случае, больше работы) для будущих разработчиков. Поэтому некоторые предлагают избегать использования статических методов, если в них нет особой необходимости.
Марво 04
8

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

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

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

Пол Сасик
источник
1
Вау, просто неправильно. Вся суть разницы (ответ на вопрос) в том, насколько сложнее впоследствии исправить код, чтобы добавить второй экземпляр. Это сделать намного сложнее, если вы использовали статические методы. Это все равно, что сказать: «Глобалы хороши в ваших ограниченных условиях», когда вся проблема с глобалами заключается в изменении условий.
Bill K
@Bill K: Я согласен с вами, и я бы использовал синглтон, если бы вообще была какая-то сложность. Но я пытался ответить на вопрос с точки зрения ОП и подумал, ну да, думаю, в этом очень ограниченном случае это перебор. Конечно, я игнорировал проблемы архитектуры или масштабируемости, а также массу других соображений. Должен ли я включить это в качестве предостережения в свой ответ с объяснением того, почему кто-то всегда должен использовать синглтон ... что, безусловно, вызвало бы отрицательные голоса со стороны других?
Пол Сасик
5

Во-первых, я просто хочу сказать, что я не нахожу особого применения паттерну Синглтон. Зачем нужно держать один объект во всем приложении? Что, если я хочу подключиться к другому серверу баз данных, особенно для баз данных? Мне каждый раз приходится отключаться и снова подключаться ...? Тем не мение...

У использования глобальных переменных в приложении есть несколько недостатков (что и делает традиционное использование шаблона Singleton):

  • Сложно для модульного тестирования
  • Проблемы с внедрением зависимостей
  • Может создавать проблемы с блокировкой (многопоточное приложение)

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

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

class Single {

    static private $_instance = false;

    public function __construct() {
        if (self::$_instance)
           throw new RuntimeException('An instance of '.__CLASS__.' already exists');

        self::$_instance = true;
    }

    private function __clone() {
        throw new RuntimeException('Cannot clone a singleton class');
    }

    public function __destruct() {
        self::$_instance = false;
    }

}

$a = new Single;
$b = new Single; // error
$b = clone($a); // error
unset($a);
$b = new Single; // works

Это поможет по первым пунктам, упомянутым выше: модульное тестирование и внедрение зависимостей; при этом убедитесь, что в вашем приложении существует единственный экземпляр класса. Например, вы можете просто передать полученный объект вашим моделям (шаблон MVC) для использования.

сетевой кодер
источник
5

Просто подумайте, чем ваше решение отличается от того, что представлено в документации PHP. На самом деле, есть только одна «небольшая» разница: ваше решение обеспечивает абонент геттера с PDOэкземпляром, в то время как один в документации обеспечивает звонящие из Database::singletonс Databaseэкземпляром (они затем используют сорбент на том , что , чтобы получитьPDO экземпляр).

Итак, к какому выводу мы пришли?

  • В коде документации вызывающие абоненты получают Databaseэкземпляр. DatabaseКласс может выставить (на самом деле, он должен выставить , если вы собираетесь на все эти проблемы) интерфейс богаче или более высокого уровня , чемPDO объект он заворачивает.
  • Если вы измените свою реализацию так, чтобы она возвращала другой (более богатый) тип, чем PDO, то две реализации эквивалентны. Нет никакой пользы от выполнения ручного внедрения.

С практической точки зрения синглтон - довольно противоречивая модель. Это в основном потому, что:

  • Этим злоупотребляют. Начинающим программистам гораздо легче разобраться в синглтоне, чем в других шаблонах. Затем они продолжают применять свои новые знания повсюду, даже если проблему можно решить лучше без синглтона (когда вы держите молоток, все выглядит как гвоздь).
  • В зависимости от языка программирования реализация синглтона герметичным и герметичным способом может оказаться титанической задачей (особенно, если у нас есть продвинутые сценарии: синглтон, зависящий от другого синглтона, синглтоны, которые можно уничтожить и воссоздать, и т. Д. ). Просто попробуйте найти "окончательную" реализацию синглтона на C ++, смею вас (я владею новаторским современным дизайном C ++ Андрея Александреску, который документирует большую часть беспорядка).
  • Это накладывает дополнительную рабочую нагрузку как при кодировании синглтона, так и при написании кода для доступа к нему, рабочая нагрузка, без которой вы можете обойтись, следуя нескольким добровольным ограничениям на то, что вы пытаетесь делать с переменными вашей программы.

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

Джон
источник
2

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

Гонки легкости на орбите
источник
2

При программировании нет «правильного» и «неправильного»; есть «хорошая практика» и «плохая практика».

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

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

иметь глобальные объекты - не всегда плохая практика. Если вы знаете, что собираетесь использовать его глобально / везде / все время, это может быть одним из немногих исключений. Однако глобальные переменные обычно считаются «плохой практикой» так же, gotoкак и плохой практикой.

zzzzBov
источник
2

Я вообще не вижу в этом смысла. Если вы реализовали класс таким образом, что строка подключения принималась в качестве параметра конструктора и поддерживала список объектов PDO (по одному для каждой уникальной строки подключения), тогда, возможно, была бы некоторая выгода, но реализация синглтона в этот случай кажется бессмысленным занятием.

Келл
источник
1

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

FooLman
источник