[DICA] Trait para Singleton
Algo me diz que esse tópico deveria ficar no Lab de scripts. Qualquer coisa fiquem à vontade para mover.
É isso aí, galera! Com o advento do PHP 5.4, ganhamos uma poderosa feature chamada Trait), que tem por objetivo servir de template para classes e que complementa a funcionalidade de classes Abstratas. De certa forma, ela provê ao PHP a funcionalidade de múltipla herança. Para maiores informações, consultem o manual.
Se você já ouviu falar em OOP e também já ouviu falar sobre Design Patterns, há uma enorme chance de conhecer o polêmico padrão Singleton. Amado pelos novatos, causa paúra nos mais experientes por ser, de longe, o Design Pattern mais incorretamente utilizado pelos programadores em geral! O @João Batista Neto escreveu uma aplicação prática sobre Singleton aqui.
Um problema chato com a implementação de Singleton é que ela inibe a herança, uma vez que a própria classe deve manipular sua(s) instância(s). Isso quer dizer que, toda vez que tivermos que escrever uma classe que seja um Singleton, o código a seguir deveria ser embarcado:
<?php
class MinhaClasseQualquer
{
private static $_instance = NULL;
// Outras propriedades de MinhaClasseQualquer
final protected function __construct()
{
self::$_instance =& $this;
}
final private function __clone()
{}
final public static function getInstance()
{
return self::$_instance ? self::$instance : new self();
}
// Abaixo vem o resto da implementação de MinhaClasseQualquer
}
Independente de se tratar do mesmo domínio ou aplicação, invariavelmente chegará o dia em que precisaremos declarar uma segunda classe que também seja um Singleton. Solução? Ctrl + C --- Ctrl + V!! DRY!
A partir do PHP 5.4, podemos isolar a implementação de Singleton em uma Trait e aplicá-la quando precisarmos que alguma classe se comporte como tal:
Singleton.php
<?php
trait Singleton
{
private static $_instance = NULL;
final protected function __construct()
{
self::$_instance =& $this;
}
final private function __clone()
{}
final public static function getInstance()
{
return self::$_instance ? self::$_instance : new self();
}
}
MeuSingleton.php
<?php
class MeuSingleton
{
use Singleton;
private $prop;
public function setProp($value)
{
$this->prop = $value;
}
public function getProp()
{
return $this->prop;
}
}
Qualquer classe posterior que precise implementar Singleton, basta adicionar a linha 5, "use Singleton;" e todo o comportamento será importado para dentro da nova classe.
MeuOutroSingleton.php
<?php
class MeuOutroSingleton
{
use Singleton;
private $otherProp;
public function setOtherProp($value)
{
$this->otherProp = $value;
}
public function getOtherProp()
{
return $this->otherProp;
}
}
Testando:
<?php
require 'Singleton.php';
require 'MeuSingleton.php';
require 'MeuOutroSingleton.php';
$exemploSingleton1 = MeuSingleton::getInstance();
$exemploSingleton2 = MeuSingleton::getInstance();
$testeDeEscopo = MeuOutroSingleton::getInstance();
// Configurando nosso "testador"
// Quando um teste falhar, irá imprimir "Afirmação incorreta: __afirmação__"
assert_options(ASSERT_CALLBACK, function ($file, $line, $code) {
echo "Afirmação incorreta {$code}." . PHP_EOL;
});
// Impedimos o PHP de lançar avisos quando afirmações falharem
assert_options(ASSERT_WARNING, FALSE);
// Testando
assert('is_null($exemploSingleton2->getProp())');
// Note que alteraremos o valor de $exemploSingleton1 e
// testaremos o valor de $exemploSingleton2
$exemploSingleton1->setProp(1);
assert('$exemploSingleton2->getProp() === 1');
// Golpe de misericórdia, MeuOutroSingleton não deve
// compartilhar a mesma interface de MeuSingleton
assert('method_exists($testeDeEscopo, "getProp"))');
Nota: Pra quem não está acostumado com assertions), a regra básica é que você faz uma afirmação. Se ela for verdadeira, o script passa sem erros, caso não, uma função pode ser lançada - como é o caso do exemplo - um aviso pode será lançado (por padrão) e pode, também, encerrar a execução do script em caso de falhas. Novamente, para maiores informações, consulte o manual.
Bom, é isso aí, agora com o PHP 5.4 é possível encher sua implementação de Singletons mal projetados reaproveitar a estrutura Singleton, diminuindo código e poupando tempo!
Até a próxima. :bye:
Discussão (7)
Carregando comentários...