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!