В чем преимущество использования singleton вместо глобального для соединений с базой данных в PHP? Я чувствую, что использование singleton вместо глобального делает код излишне сложным.
$conn = new PDO(...); function getSomething() { global $conn; . . . }
class DB_Instance { private static $db; public static function getDBO() { if (!self::$db) self::$db = new PDO(...); return self::$db; } } function getSomething() { $conn = DB_Instance::getDBO(); . . . }
Если есть лучший способ инициализировать соединение с базой данных, отличное от глобального или однострочного, укажите его и опишите преимущества, которые он имеет над глобальным или одноточечным.
Я знаю, что это старо, но ответ Dr8k был почти там.
Когда вы планируете писать фрагмент кода, предположите, что он изменится. Это не означает, что вы принимаете такие изменения, которые он будет поднимать на этом в какой-то момент в будущем, а скорее будут сделаны какие-то изменения.
Сделать цель смягчить боль внесения изменений в будущем: глобальный опасен, потому что трудно управлять в одном месте. Что делать, если я хочу, чтобы в будущем этот контекст подключения к базе данных был известен? Что, если я хочу, чтобы он закрывался и снова открывался каждый раз, когда он использовался. Что делать, если я решаю, что в интересах масштабирования моего приложения я хочу использовать пул из 10 подключений? Или настраиваемое количество подключений?
Фабрика singleton дает вам такую гибкость. Я установил его с очень небольшой сложностью и получаю больше, чем просто доступ к тому же соединению; Я получаю возможность изменить, как это соединение передается мне позже, простым способом.
Обратите внимание, что я говорю о фабрике singleton, а не просто одинарной . Существует очень мало различий между одноэлементным и глобальным, истинным. И из-за этого нет причин иметь одноэлементное соединение: зачем вам тратить время на настройку, когда вы могли бы создать обычный глобальный?
То, что завод получает от вас, – это то, почему нужно подключаться, и отдельное место, чтобы решить, какие соединения (или соединение) вы собираетесь получить.
class ConnectionFactory { private static $factory; private $db; public static function getFactory() { if (!self::$factory) self::$factory = new ConnectionFactory(...); return self::$factory; } public function getConnection() { if (!$this->db) $this->db = new PDO(...); return $this->db; } } function getSomething() { $conn = ConnectionFactory::getFactory()->getConnection(); . . . }
Затем, через 6 месяцев, когда ваше приложение станет супер известным и получив dugg и slashdotted, и вы решите, что вам нужно больше одного соединения, все, что вам нужно сделать, это реализовать некоторый пул в методе getConnection (). Или, если вы решите, что хотите иметь оболочку, которая реализует ведение журнала SQL, вы можете передать подкласс PDO. Или, если вы решите, что хотите получить новое соединение при каждом вызове, вы можете сделать это. Это гибкий, а не жесткий.
16 строк кода, включая брекеты, что сэкономит вам часы, часы и часы рефакторинга, что-то ужасно похожее на линию.
Обратите внимание, что я не рассматриваю этот «Feature Creep», потому что я не выполняю никаких функций в первом раунде. Это пограничная линия «Future Creep», но в какой-то момент мысль о том, что «кодирование завтрашнего дня» всегда плохая вещь, не преследует меня.
Я не уверен, что могу ответить на ваш конкретный вопрос, но хотел предположить, что глобальные / одиночные объекты соединения могут быть не лучшей идеей, если это, если для веб-системы. СУБД, как правило, предназначены для эффективного управления большим количеством уникальных соединений. Если вы используете глобальный объект соединения, вы делаете пару вещей:
Заставляя страницы делать все подключения к базе данных последовательно и убивать любые попытки загрузки асинхронных страниц.
Потенциально удерживать открытые блокировки элементов базы данных дольше, чем необходимо, замедляя общую производительность базы данных.
Максимальное количество одновременных соединений, поддерживаемых вашей базой данных, и блокирование доступа новых пользователей к ресурсам.
Я уверен, что есть и другие потенциальные последствия. Помните, что этот метод будет пытаться поддерживать соединение с базой данных для каждого пользователя, обращающегося к сайту. Если у вас есть только один или два пользователя, это не проблема. Если это общедоступный веб-сайт, и вы хотите трафик, тогда масштабируемость станет проблемой.
[РЕДАКТИРОВАТЬ]
В более масштабных ситуациях создание новых соединений каждый раз, когда вы попадаете в базу данных, может быть плохим. Однако ответ заключается не в том, чтобы создать глобальное соединение и повторно использовать его для всего. Ответ – объединение пулов.
При объединении соединений поддерживается несколько различных соединений. Когда приложение требуется подключение, первое доступное соединение из пула извлекается, а затем возвращается в пул после выполнения его работы. Если запрашивается соединение и нет ни одного из них, произойдет одно из двух: а) если максимальное количество разрешенных соединений не достигнуто, открывается новое соединение или б) приложение вынуждено ждать, пока соединение станет доступным ,
Примечание. В языках .Net пул соединений по умолчанию обрабатывается объектами ADO.Net (строка подключения задает всю необходимую информацию).
Спасибо Крэду за комментирование этого.
Метод singleton был создан, чтобы убедиться, что существует только один экземпляр любого класса. Но, поскольку люди используют его как способ ускорить глобализацию, он становится известен как ленивое и / или плохое программирование.
Поэтому я бы проигнорировал глобальный и Синглтон, поскольку оба они не являются ООП.
То, что вы искали, – это инъекция зависимости .
Вы можете проверить легко читаемую информацию на основе PHP, связанную с инъекцией зависимостей (с примерами) по адресу http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection
Оба шаблона обеспечивают одинаковый сетевой эффект, обеспечивая единую точку доступа для вызовов в базе данных.
С точки зрения конкретной реализации синглтон имеет небольшое преимущество в том, что вы не инициируете соединение с базой данных до тех пор, пока не запросит хотя бы один из ваших других методов. На практике в большинстве приложений, которые я написал, это не имеет большого значения, но это потенциальное преимущество, если у вас есть несколько страниц / путей выполнения, которые вообще не производят никаких вызовов базы данных, поскольку эти страницы не будут когда-либо запрашивают подключение к базе данных.
Еще одно незначительное отличие состоит в том, что глобальная реализация может попирать другие имена переменных в приложении непреднамеренно. Маловероятно, что вы когда-нибудь случайно объявите еще одну глобальную ссылку на $ db, хотя возможно, что вы можете перезаписать ее случайно (скажем, вы пишете if ($ db = null), когда вы хотели написать if ($ db == null). Объект singleton предотвращает это.
Если вы не собираетесь использовать постоянное соединение, и есть случаи, когда вы этого не делаете, я считаю, что синглтон будет концептуально более приемлемым, чем глобальный в дизайне OO.
В настоящей OO-архитектуре одноэлемент более эффективен, чем создание нового экземпляра объекта каждый раз.
На данном примере я не вижу причин использовать синглтоны. Как правило, если моя единственная проблема заключается в том, чтобы разрешить один экземпляр объекта, если язык позволяет это, я предпочитаю использовать глобальные переменные
В общем, я бы использовал singleton для подключения к базе данных … Вы не хотите создавать новое соединение каждый раз, когда вам нужно взаимодействовать с базой данных … Это может повредить производительность и пропускную способность вашей сети … Зачем создавать новый, когда есть один доступный … Только мои 2 цента …
RWendi
Это довольно просто. Никогда не используйте глобальный OR Singleton.