Jump to content


Photo

Design Pattern: Singleton


  • Faça o login para participar
6 replies to this topic

#1 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 20/10/2008, 08:51

Opa... ;-)

Tenho lido sobre o design pattern Singleton e me deparei com uma situação que gerou-me uma dúvida. Eis meu código:

<?php

abstract class Singleton
{
	private static $_instance = array();

	public static function getInstance($class_name, $identifier = null)
	{
		if (!empty($identifier)) {
			if (!isset(self::$_instance[$class_name][$identifier])) {
				self::$_instance[$class_name][$identifier] = new $class_name($identifier);
			}

			return self::$_instance[$class_name][$identifier];
		}

		if (!isset(self::$_instance[$class_name])) {
			self::$_instance[$class_name] = new $class_name;
		}

		return self::$_instance[$class_name];
	}

	abstract public static function factory($identifier = null);

	public function __clone()
	{
		throw new BadMethodCallException('Clone is not allowed.');
	}

	public function __wakeup()
	{
		throw new BadMethodCallException('Deserializing is not allowed.');
	}
}

class A extends Singleton
{
	protected function __construct()
	{
		// init
	}

	public static function factory($identifier = null)
	{
		return parent::getInstance(__CLASS__, $identifier);
	}
}

class B extends Singleton
{
	private $_identifier = null;

	protected function __construct($identifier)
	{
		$this->_identifier = $identifier;
	}

	public static function factory($identifier = null)
	{
		return parent::getInstance(__CLASS__, $identifier);
	}

	public function getIdentifier()
	{
		return $this->_identifier;
	}
}

$A  = A::factory();
$B1 = B::factory('foo');
print $B1->getIdentifier(); // Saída: foo
$B2 = B::factory('bar');
print $B2->getIdentifier(); // Saída: bar

?>
Neste caso, a propriedade privada Singleton::$_instance teria a seguinte estrutura:

Array
(
	[A] => A Object
		(
		)

	[B] => Array
		(
			[foo] => B Object
				(
					[_identifier:private] => foo
				)

			[bar] => B Object
				(
					[_identifier:private] => bar
				)

		)
)
Minha dúvida é: esta utilização do padrão Singleton é válida? Ou eu, aqui, estou quebrando alguma "regra"? :ponder:

Obrigado,
[]’s :DAté mais

#2 fly2k

fly2k

    Super Veterano

  • Usuários
  • 2262 posts
  • Sexo:Não informado

Posted 21/10/2008, 09:51

Confesso a você que ainda me gera algumas dúvidas sobre os design patterns existents. Porém é algo que está consolidando com o uso.

A questão é que o Singleton é um padrão que permite uma ÚNICA instância de uma classe.

E o seu código cria uma instância para cada identificador. O que não é o propósito do do Singleton.

Ou entendi errado o seu código?
Quer aprender PHP? -> www.manjaphp.com.br
Tutoriais, código colaborativo (pastebin), curso de PHP, artigos e etc.

#3 Marcos Aurélio

Marcos Aurélio

    Das terras geladas da Sibéria

  • Usuários
  • 208 posts
  • Sexo:Masculino

Posted 21/10/2008, 12:33

fly2k, exatamente. A não ser que eu tenha entendido o código erroneamente, você cria uma instância para cada objeto, com o key identifier associando. O pattern Singleton propõe resolver problemas no qual você apenas pode ter uma instância de uma determinada classe em toda a aplicação, como é caso de conexões com o banco de dados, quando trabalha-se com templates etc. Nesse caso, você estaria utilizando o Singleton não para esta finalidade, mas sim, para "agrupar" suas várias instâncias [se é que entendi certo].

Abraços!

#4 Paulo Freitas

Paulo Freitas

    ××××××× LRU #456504 ××××××× ××××××× LRM #364686 ×××××××

  • Ex-Admins
  • 5612 posts
  • Sexo:Masculino
  • Localidade:Campinas - SP

Posted 21/10/2008, 12:37

Confesso a você que ainda me gera algumas dúvidas sobre os design patterns existents. Porém é algo que está consolidando com o uso.

A questão é que o Singleton é um padrão que permite uma ÚNICA instância de uma classe.

E o seu código cria uma instância para cada identificador. O que não é o propósito do do Singleton.

Ou entendi errado o seu código?

Pois bem, essa idéia do Singleton é a mesma que compreendi, de se ter uma única instância de uma classe sendo aproveitada todas as vezes em que a mesma seja requisitada. E foi aí que me apareceu a dúvida, he he he. :D
No caso da classe A, tudo acontece como deveria*. O "problema" é na classe B, onde o funcionamento da classe depende de um identificador. Para um melhor compreendimento, suponhamos que a classe B seja uma classe de conexão à base de dados e que cada instância dela se refere a uma conexão diferente (isto é, com parâmetros diferentes). Isso que me despertou a danada. :P O funcionamento em si segue o intento, só não sei se este é modo correto de se fazer isto. :ponder:
Eu já cheguei a pensar em ter um vetor próprio de instâncias na classe B, mas aí, além de não conseguir terminar o raciocínio de implementação, eu já perdi a noção de todo resto. :P

E agora, ficou mais fácil? :)

* Ou melhor, ao menos aparentemente... Está correta a visibilidade protected no construtor das classes A e B? O pattern define private (para que não se chame o construtor diretamente), mas esta implementação (que não foi por minha pessoa inventada) não permitiria, caso contrário o método Singleton::getInstance() deixaria de funcionar. :(

[]’s :DAté mais

#5 fly2k

fly2k

    Super Veterano

  • Usuários
  • 2262 posts
  • Sexo:Não informado

Posted 21/10/2008, 14:48

Sobre o construtor ser protected, isso me surpreendeu, mas realmente funciona. :P

Sobre o padrão, na verdade isso foge ao sigleton. Pois na verdade você precisa de várias instâncias de uma mesma classe, mas com um identificador diferente.

Vou dar uma olhada se se encaixa em algum outro padrão, ou se existe algum outro padrão que faça isso.

Na verdade, isso é mais um factory. Mas vamos ver.

----Atualizando... Não achei nada que se encaixasse. Talvez deva existir. Mas enfim.
Quer aprender PHP? -> www.manjaphp.com.br
Tutoriais, código colaborativo (pastebin), curso de PHP, artigos e etc.

#6 hlegius

hlegius

    Turista

  • Usuários
  • 58 posts
  • Sexo:Masculino
  • Localidade:Guarulhos, SP
  • Interesses:Google Talk: hlegius em gmail ponto com

Posted 22/10/2008, 07:07

Como o pessoal disse acima, a idéia do Singleton é algo único.

Repare que você herda o Singleton. Essa construção eu achei meio estranha. O correto talvez, fosse injetar o Singleton na sua demais classes via construtor ou get/set.

Uma coisa que chamou minha atenção foi você ter usado o Singleton como abstrata. A pattern diz que o "certo" é você tê-la como real, porém, privada. Veja:

class Singleton {
	private static $unico;
	private $count = 0;

	private function Singleton() {}


	public static function getInstance() {
		if(!(self::$unico instanceof Singleton)) {
			self::$unico = new Singleton();
		}

		return self::$unico;
	}


	public function salve() {
		$this->count += 1;
		echo 'Salvou ! Total de contagem: ' . $this->count . '<br />';
	}
}

E sua aplicação teste:

<?php
$singleton = Singleton::getInstance();
$singleton->salve();
?>

Sobre sua necessidade de ter configurações diferentes como citou acima, bem, poderia ser aplicada de forma simples. Na minha idéia - depende do que varia e do seu real propósito com isto - você poderia injetar as informações em tempo de execução numa classe de configuração. Talvez se essa classe de configuração instanciasse outras ela poderia ser uma factory ou caso apenas junte um monte de operações, seria uma fachada.

O importante é não se prender as patterns. Tente criar algo usando o design OO puro. Mas se sua implementação parecer alguma pattern, daí investigue X)

Abraço!

Edição feita por: hlegius, 22/10/2008, 07:09.

hlegius.
http://www.hlegius.pro.br | http://www.programe.me
ArchLinux - A simple lightweight Linux distribution

#7 fly2k

fly2k

    Super Veterano

  • Usuários
  • 2262 posts
  • Sexo:Não informado

Posted 22/10/2008, 13:54

É, design patterns são soluções elegantes para problemas já conhecidos..... nova necessidade... outro código..ou uma melhoria.... mas naum se preocupe se eh ou não um pattern
Quer aprender PHP? -> www.manjaphp.com.br
Tutoriais, código colaborativo (pastebin), curso de PHP, artigos e etc.




1 user(s) are reading this topic

0 membro(s), 1 visitante(s) e 0 membros anônimo(s)

IPB Skin By Virteq