¿Cuál es el beneficio de usar singleton en lugar de global para conexiones de base de datos en PHP? Siento que usar singleton en lugar de global hace que el código sea innecesariamente complejo.
Codificar con Global
$conn = new PDO(...);
function getSomething()
{
global $conn;
.
.
.
}
Código con Singleton
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();
.
.
.
}
Si hay una mejor forma de inicializar la conexión de base de datos que no sea global o singleton, por favor menciónela y describa las ventajas que tiene sobre global o singleton.
php
design-patterns
singleton
Imran
fuente
fuente
Respuestas:
Sé que esto es antiguo, pero la respuesta de Dr8k casi estaba ahí.
Cuando esté considerando escribir un fragmento de código, asuma que va a cambiar. Eso no significa que esté asumiendo el tipo de cambios que habrá generado en algún momento en el futuro, sino que se hará algún tipo de cambio.
Conviértalo en un objetivo para mitigar el dolor de hacer cambios en el futuro: un mundo global es peligroso porque es difícil de administrar en un solo lugar. ¿Qué sucede si quiero que esa conexión de base de datos sea consciente del contexto en el futuro? ¿Qué pasa si quiero que se cierre y se vuelva a abrir cada quinta vez que se usa? ¿Qué pasa si decido que, en aras de escalar mi aplicación, quiero usar un grupo de 10 conexiones? ¿O un número configurable de conexiones?
Una fábrica de singleton le brinda esa flexibilidad. Lo configuro con muy poca complejidad adicional y obtengo más que solo acceso a la misma conexión; Gano la capacidad de cambiar la forma en que se me pasa esa conexión más adelante de una manera simple.
Tenga en cuenta que digo singleton factory en lugar de simplemente singleton . Hay muy poca diferencia entre un singleton y un global, cierto. Y debido a eso, no hay razón para tener una conexión singleton: ¿por qué dedicarías el tiempo a configurar eso cuando podrías crear un global regular en su lugar?
Lo que le ofrece una fábrica es un por qué obtener conexiones y un lugar separado para decidir qué conexiones (o conexión) obtendrá.
Ejemplo
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(); . . . }
Luego, en 6 meses, cuando su aplicación sea súper famosa y se esté volviendo loca y usted decida que necesita más de una conexión, todo lo que tiene que hacer es implementar algunas agrupaciones en el método getConnection (). O si decide que quiere un contenedor que implemente el registro SQL, puede pasar una subclase PDO. O si decide que quiere una nueva conexión en cada invocación, puede hacerlo. Es flexible, en lugar de rígido.
16 líneas de código, incluidas llaves, que le ahorrarán horas y horas y horas de refactorización a algo inquietantemente similar en el futuro.
Tenga en cuenta que no considero esto "Feature Creep" porque no estoy implementando ninguna característica en la primera ronda. Es la línea fronteriza "Future Creep", pero en algún momento, la idea de que "programar para el mañana hoy" es siempre algo malo no me gusta.
fuente
return self::$factory->getConnection();
lugar dereturn self::$factory;
?No estoy seguro de poder responder a su pregunta específica, pero quería sugerir que los objetos de conexión global / singleton pueden no ser la mejor idea si se trata de un sistema basado en web. Los DBMS generalmente están diseñados para administrar un gran número de conexiones únicas de manera eficiente. Si está utilizando un objeto de conexión global, entonces está haciendo un par de cosas:
Obligar a sus páginas a hacer todas las conexiones de base de datos secuencialmente y eliminar cualquier intento de carga de páginas asíncronas
Potencialmente mantener los bloqueos abiertos en los elementos de la base de datos más de lo necesario, lo que ralentiza el rendimiento general de la base de datos.
Maximizar el número total de conexiones simultáneas que su base de datos puede admitir y bloquear el acceso de nuevos usuarios a los recursos.
Estoy seguro de que también hay otras posibles consecuencias. Recuerde, este método intentará mantener una conexión de base de datos para cada usuario que acceda al sitio. Si solo tiene uno o dos usuarios, no hay problema. Si se trata de un sitio web público y desea tráfico, la escalabilidad se convertirá en un problema.
[EDITAR]
En situaciones de mayor escala, crear nuevas conexiones cada vez que acceda a la base de datos puede ser malo. Sin embargo, la respuesta no es crear una conexión global y reutilizarla para todo. La respuesta es la agrupación de conexiones.
Con la agrupación de conexiones, se mantienen varias conexiones distintas. Cuando la aplicación requiere una conexión, se recupera la primera conexión disponible del grupo y luego se devuelve al grupo una vez que se realiza su trabajo. Si se solicita una conexión y no hay ninguna disponible, sucederá una de estas dos cosas: a) si no se alcanza el número máximo de conexiones permitidas, se abre una nueva conexión, ob) la aplicación se ve obligada a esperar a que una conexión esté disponible .
Nota: En los lenguajes .Net, la agrupación de conexiones es manejada por los objetos ADO.Net por defecto (la cadena de conexión establece toda la información requerida).
Gracias a Crad por comentar esto.
fuente
El método singleton se creó para asegurarse de que solo hubiera una instancia de cualquier clase. Pero, debido a que la gente lo usa como una forma de atajar la globalización, se lo conoce como programación perezosa y / o mala.
Por lo tanto, ignoraría global y Singleton ya que ambos no son realmente OOP.
Lo que buscabas es una inyección de dependencia .
Puede consultar información fácil de leer basada en PHP relacionada con la inyección de dependencia (con ejemplos) en http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection
fuente
Ambos patrones logran el mismo efecto de red, proporcionando un único punto de acceso para sus llamadas a la base de datos.
En términos de implementación específica, el singleton tiene una pequeña ventaja de no iniciar una conexión a la base de datos hasta que al menos uno de sus otros métodos lo solicite. En la práctica, en la mayoría de las aplicaciones que he escrito, esto no hace mucha diferencia, pero es una ventaja potencial si tiene algunas páginas / rutas de ejecución que no realizan ninguna llamada a la base de datos, ya que esas páginas no lo harán. alguna vez solicite una conexión a la base de datos.
Otra pequeña diferencia es que la implementación global puede pisotear otros nombres de variables en la aplicación sin querer. Es poco probable que alguna vez declare accidentalmente otra referencia global $ db, aunque es posible que pueda sobrescribirla accidentalmente (digamos, escribe if ($ db = null) cuando quería escribir if ($ db == null). El objeto singleton evita eso.
fuente
Si no va a utilizar una conexión persistente, y hay casos para no hacerlo, creo que un singleton es conceptualmente más aceptable que un global en el diseño OO.
En una verdadera arquitectura OO, un singleton es más efectivo que crear una nueva instancia del objeto cada vez.
fuente
En el ejemplo dado, no veo ninguna razón para usar singletons. Como regla general, si mi única preocupación es permitir una sola instancia de un objeto, si el lenguaje lo permite, prefiero usar globales
fuente
En general, usaría un singleton para una conexión de base de datos ... No desea crear una nueva conexión cada vez que necesite interactuar con la base de datos ... Esto podría afectar el rendimiento y el ancho de banda de su red ... ¿Por qué crear una uno nuevo, cuando hay uno disponible ... Solo mis 2 centavos ...
RWendi
fuente
Es muy sencillo. Nunca use OR Singleton global.
fuente
Como consejo tanto singleton como global son válidos y se pueden unir dentro de un mismo sistema, proyecto, plugin, producto, etc ... En mi caso, hago productos digitales para web (plugin).
Solo uso singleton en la clase principal y lo uso por principio. Casi no lo uso porque sé que la clase principal no lo instanciará nuevamente
<?php // file0.php final class Main_Class { private static $instance; private $time; private final function __construct() { $this->time = 0; } public final static function getInstance() : self { if (self::$instance instanceof self) { return self::$instance; } return self::$instance = new self(); } public final function __clone() { throw new LogicException("Cloning timer is prohibited"); } public final function __sleep() { throw new LogicException("Serializing timer is prohibited"); } public final function __wakeup() { throw new LogicException("UnSerializing timer is prohibited"); } }
Uso global para casi todas las clases secundarias, ejemplo:
<?php // file1.php global $YUZO; $YUZO = new YUZO; // YUZO is name class
mientras que en tiempo de ejecución puedo usar Global para llamar a sus métodos y atributos en la misma instancia porque no necesito otra instancia de mi clase de producto principal.
<?php // file2.php global $YUZO; $YUZO->method1()->run(); $YUZO->method2( 'parameter' )->html()->print();
Lo que obtengo con el global es usar la misma instancia para poder hacer que el producto funcione porque no necesito una fábrica para instancias de la misma clase, generalmente la fábrica de instancias es para sistemas grandes o para propósitos muy raros.
In conclusion:
, debes si ya entiendes bien que es el anti-patrón Singleton y entiendes el Global , puedes usar una de las 2 opciones o mezclarlas pero si te recomiendo no abusar ya que hay muchos programadores que son muy excepcionales y fieles a la programación OOP, úsala para las clases principales y secundarias que usas mucho dentro del tiempo de ejecución. (Te ahorra mucha CPU). 😉fuente