+3

O Design Pattern Singleton, na prática

criado por Alex Weber em 01/06/2009 11:39pm
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.

<?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?

Comentários:

Mostrando 1 - 1 de 1 comentários
Show de bola cara!

Parabéns!
31/01/2011 2:45pm (~7 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)