O Design Pattern Singleton, na prática
E se...
Agora vou apresentar o problema: E se a gente quisesse, por qualquer motivo, não só apenas somente poder ter uma instância da classe em qualquer devido momento mas ter sempre a mesma instância?
Parece fácil? Vamos ver na prática!
Vamos modificar a classe anterior para que armazene a hora em que foi criada e criar também um método para retornar o valor.
E vamos testar da seguinte maneira:
Legal, agora dê alguns refresh... repare que a hora fica mudando.
Até aí isto é esperado né? Afinal não estamos usando sessões para armazenar a classe entre cada refresh.
Bom vamos então implementar sessões para ver se a gente consegue ter sempre a mesma instância do objeto inicializado na primeira vez que a página for carregada:
Mas que p*** é essa Batiman?
Pois é... não funciona conforme o esperado...
A explicação é a seguinte: entre um refresh e o outro o objeto é serializado e "guardado pra depois". Quando a execução volta, o objeto serializado é "deserializado" e preparado para continuar funcionando normalmente.
O problema reside no fato de variáveis estáticas não serem serializadas.
E aí, será que existe alguma solução?
Agora vou apresentar o problema: E se a gente quisesse, por qualquer motivo, não só apenas somente poder ter uma instância da classe em qualquer devido momento mas ter sempre a mesma instância?
Parece fácil? Vamos ver na prática!
Vamos modificar a classe anterior para que armazene a hora em que foi criada e criar também um método para retornar o valor.
<?php class SingletaoMelhorzinho{ // variável estática da classe protected static $instance; // variavel para a hora em que a classe foi instanciada protected $hora; // demarcado como private para evitar a instanciação direta private function __construct() { // armazena a hora em que a classe é instanciada (de uma maneira legível para nós) $this->hora = date('H:i:s'); } // método para retornar a hora em que foi a classe foi instanciada public function getTime() { return $this->hora; } // private para evitar que a classe seja clonada private function __clone() { } // método estático para poder ser chamado sem que exista uma instância da classe public static function getInstance() { // verifica se a variável estática é uma instância de si mesmo if(!self::$instance instanceof self){ // se não for, a classe se instancia e armazena a instância na variável estática self::$instance = new self(); } // retorna a variável estática return self::$instance; } }
E vamos testar da seguinte maneira:
$foo = SingletaoMelhorzinho::getInstance(); echo 'A classe foi instanciada as ' . $foo->getTime();
Legal, agora dê alguns refresh... repare que a hora fica mudando.
Até aí isto é esperado né? Afinal não estamos usando sessões para armazenar a classe entre cada refresh.
Bom vamos então implementar sessões para ver se a gente consegue ter sempre a mesma instância do objeto inicializado na primeira vez que a página for carregada:
require_once('SingletaoMelhorzinho.php'); session_start(); // IMPORTANTE! Como a classe será armazenada na sessão, faça o "include" dela antes de iniciar a sessão! $_SESSION['foo'] = SingletaoMelhorzinho::getInstance(); echo 'A classe foi instanciada as ' . $_SESSION['foo']->getTime();
Mas que p*** é essa Batiman?
Pois é... não funciona conforme o esperado...
A explicação é a seguinte: entre um refresh e o outro o objeto é serializado e "guardado pra depois". Quando a execução volta, o objeto serializado é "deserializado" e preparado para continuar funcionando normalmente.
O problema reside no fato de variáveis estáticas não serem serializadas.
E aí, será que existe alguma solução?
Parabéns!