Patrón Singleton
Qué es?
Es un patrón de diseño. Su finalidad es crear un objeto único para toda la aplicación, así mejoramos el rendimiento, ya que la generación de un objeto cuesta algo (imaginemos dinero). Se genera un punto de acceso global al objeto.
Ejemplos en Magento 2
El ejemplo más general es el ObjectManager: lib/internal/Magento/Framework/App/ObjectManager.php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
/* Generar un objeto nuevo de producto */
$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
/* Tomar un objeto del tipo compartido de request
$request = $objectManager->get(\Magento\Framework\App\RequestInterface::class);
Vamos a analizar esta clase ObjectManager.
Esta clase tiene una propiedad $_instance del tipo estático, es decir, es compartida en toda la aplicación y es de acceso inmediato, sin necesidad de invocar objeto. El valor de la propiedad no varía de objeto a objeto.
Por ejemplo, Somos personas. Persona es una clase. Tú eres un objeto de la clase Persona, él también y yo también. Todos somos objetos de la clase Persona. Somos diferentes. Tú eres más alto que yo. Yo tengo las manos más grandes y él tiene la boca más grande. Es decir los objetos tienen valores que son propios y diferentes de los demás. Pero también tienen propiedades que tienen valores compartidos entre ellos. A esas propiedades les llamamos estáticas.
protected static $_instance;
public static function getInstance()
{
if (!self::$_instance instanceof \Magento\Framework\ObjectManagerInterface) {
throw new \RuntimeException('ObjectManager isn\'t initialized');
}
return self::$_instance;
}
¿Cómo crear clases nuestras de singleton?
La clase ObjectManager nos da 2 opciones:
- Generar objeto nuevo
- Tomar el objeto singleton si el objeto es del tipo singleton
public function create($type, array $arguments = [])
{
return $this->_factory->create($this->_config->getPreference($type), $arguments);
}
public function get($type)
{
$type = ltrim($type, '\\');
$type = $this->_config->getPreference($type);
if (!isset($this->_sharedInstances[$type])) {
$this->_sharedInstances[$type] = $this->_factory->create($type);
}
return $this->_sharedInstances[$type];
}
Ahora bien, ¿Cómo le indicamos a Magento, que una clase es del tipo compartido? Uno de los ejemplos es la clase RouterList. En el fichero di.xml, en la etiqueta type, poner el valor del atributo shared como true. ¡Ojo! Esto es si se quiere usar el método get del ObjectManager.
Normalmente utilizamos el modelo Inyccción de Dependencias para generar objetos, que son como el modelo Singleton y NO hace falta poner el atributo shared="true".
# Store/etc/frontend/di.xml
<type name="Magento\Framework\App\RouterList" shared="true">
....