Em mais um post sobre os patterns, vou falar do Singleton, dando como exemplo o Registry, um dos mais famosos usos do pattern.
O que é?
O Singleton veio com o objetivo de permitir apenas uma única instância de um objeto, sendo o que o método mágico __construct() é privado, impedindo a instanciação. Ele é similar à uma session, meio que uma variável global em forma objeto, sendo que você pode acessá-lo de qualquer parte do projeto.
Obs.: Singleton != Static Method
Representação:
Registry:
O Registry é uma forma de aplicação do Singleton bem interessante. Ele serve para guardar dados que serão necessários na aplicação toda, como instâncias de banco de dados, quando se precisa de mais de um (mesmo quando não se precisa, vai que no futuro seja necessário…).
Lembrado que o Registry pode ser aplicado de outras formas, não só com Singleton, é que está é a maneira mais usada.
Implementação: Singleton + Registry
A implementação funcionará da seguinte maneira:
class Registry{ /** * Conjunto de dados * @var instanceof ArrayObject */ private $data; /** * Aqui ficará a instancia do próprio objeto * @var instanceof self */ private static $instance; /** * Private para não permitir ser instanciado */ private function __construct(){ $this->connections = new ArrayObject; } /** * Cria a instancia do objeto * @return instanceof Registry */ public static function getInstance(){ if( !( self::$instance instanceof Registry ) ){ self::$instance = new Registry; } return self::$instance; } /** * Adiciona um dado ao Registry * @param $key Nome para reconhecimento de determinado registro * @param $value Registro * @throws InvalidArumentException Caso a key já tenha sido adicionada */ public function addElement( $key, $value ){ if( $this->data->offsetExists( $key ) ){ throw new InvalidArgumentException( sprintf( '"%s" have already added', $key ) ); } $this->data->offsetSet( $key, $value ); } /** * Remove um dado do Registry * @param $key O nome relacionado ao registro * $throws InvalidArgumentExcpeiton Caso o nome não esteja associado a algum registro */ public function removeElement( $key ){ if( !$this->data->offsetExists( $key ) ){ throw new InvalidArgumentException( sprintf( '"%s" not found', $key ) ); } $this->data->offsetUnset( $key ); } /** * Retorna um registro * @param $key Nome de registro do elemento * @return Algum valor registrado * $throws InvalidArgumentExcpeiton Caso o nome não esteja associado a algum registro */ public function getElement( $key ){ if( !$this->data->offsetExists( $key ) ){ throw new InvalidArgumentException( sprintf( '"%s" not found', $key ) ); } return $this->data->offsetGet( $key ); } /** * Retorna se um determinado nome de registro existe * @param $key Nome de registro do elemento * @return bool */ public function existsElement( $key ){ return $this->data->offsetExists( $key ); } }
Uso:
Agora você pode, por exemplo, guardar aqui quantas conexões com alguns banco de dados você quiser:
$registry = Registry::getInstance(); $connection1 = new PDO( 'mysql:host=localhost;dbname=db_test', 'user', 'pass' ); $connection1 = new PDO( 'mysql:host=localhost;dbname=db_test2', 'user', 'pass' ); $registry->addElement( 'connection_1', $connection1 ); $retistry->addElement( 'connection_2', $connection2 );
Então em qualquer lugar de sua aplicação você pode fazer isso:
$registry = Registry::getInstance(); $connection = 'connection_1'; if( $registry->existsElement( $connection ) ){ $pdo = $registry->getElement( 'connection_1' );//Ou connection_2 }
Conclusão:
Como visto, ele ajuda bastante quando se precisa de um objeto que transite por toda aplicação sem ser necessário instanciá-lo toda vez.
O Singleton também é bastante usado por alguns frameworks ao transitar dados relacionados às conexão (não me refiro ao Registry).