Publicidade   
 você está aqui: phpbrasil.com    artigos    artigo  
 
:: novos artigos ::

:: recomendado ::

MYSQL & MSQL

Compre esse livro no Submarino.com.br

:: publicidade ::


:: novos scripts ::

:: elenco phpbrasil ::

fccd
Pontos: 10353

Visite a página de perfil de Felipe Lunardi FariasFactory Method (PHP5)
por Felipe Lunardi Farias
Lista de Categorias  |  Contribua um Novo Artigo  |  Entre em Contato Conosco

Este é um tipo bem comum de padrão utilizado nos programas orientados
ao objeto. O padrão Factory Method é caracterizado por retornar uma
instância dentre muitas possíveis classes, dependendo dos dados
providos a ele.

Quem programa em JAVA já deve ter se deparado com esse método.

Vamos considerar um caso simples onde nós podemos usar uma classe
Factory. Suponha que nós temos um sistema de consulta de preços de
veículos. Informamos qual carro queremos consultar o preço, então a
classe factory nos retorna uma instância dele e então consultamos o
preço.

Note que poderiamos certamente passar a váriavel $Carro via um simples formulário HTML.

Vamos, então, dar uma olhada na implementação:
Vote aqui!
Média de Votos Atual: 6.50
Total de Votos: 20
Nota:   


<?php


/** 
Essa é nossa classe "abstrata". Note que uma classes abstratas não pode ser instanciada, ou seja, não há objatos que possam ser construídos diretamente de sua definição.
Classes abstratas deverão ser concretizadas em classes derivadas.
*/ 
Abstract Class Carro 

    
/** 
    A palavra-chave protected restringe a visibilidade do membro modificado, atributo ou     
    método, de forma que classes não-relacionadas não possam acessá-lo. Objetos da própria  
    classe, de classes derivadas desta.
    */          
    
protected $valor;

    
public function getPreco() {
        return 
$this->valor;
    }
}

// Classes que herdam caracteristicas da classe pai.
Class Vectra extends Carro {
    
public function Vectra() {
        return 
$this->valor 30000;
    }
}

Class 
Omega extends Carro {
    
public function Omega() {
        return 
$this->valor 50000;
    }
}

Class 
Golf extends Carro {
    
public function Golf() {
        return 
$this->valor 35000;
    }
}    

Class 
Gol extends Carro {
    
public function Gol() {
        return 
$this->valor 20000;
    }
}



//Note que uma classe definida como final não pode ser extendida.

Final Class CarroFactory {

    
public static function GetCarro ($TCarro){
    If (!
$TCarro)
        return 
null;
    else if( 
$TCarro=="Vectra" 
        return new 
Vectra();
    else if( 
$TCarro=="Omega" )  
        return new 
Omega();
    else if( 
$TCarro=="Golf" )   
        return new 
golf();
    else if( 
$TCarro=="Gol" )    
        return new 
gol();
    }
}


$Carro "Gol";
print 
$Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->getPreco() );

/** Veja que não precisamos utilizar nesse exemplo FACTORY um construtor!
Obs: Construtor - > é apenas invocado no momento da criação do objeto através do operador new.
*/ 

?>



<< Anterior 1 Próxima >>

 
Imprimir  |  Enviar para um Amigo


Comentários de Usuários

Bom Mesmo
publicado por Reinaldo Martinez Cabral - 2004-10-04 16:52:12

Semana passada eu precisei implementar um Factory, mas tive um problema pois precisava que a classe que é instanciada não premanece instanciada, ou seja, utilizando o exemplo acima ele eu precisaria guardar o valor do carro solicitado e ir somando os demais!
Exemplo:

Supondo que a classe acima já tenha sido implementada para somar os valores e depois imprimir!

$Carro = "Gol";
print $Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->getPreco() );
$Carro = "Golf";
print $Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->getPreco() );

print $Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->totalPreco() );

E ele retornar 55000, mas na verdade ele me retorna 35000.

Até o momento não encontrei nenhuma solução!!

Ou seja tive que refazer de outro modo!

Bom Mesmo (Corrigindo)
publicado por Reinaldo Martinez Cabral - 2004-10-04 16:54:09

Eu havia escrito assim: "precisava que a classe que é instanciada não premanece instanciada"

O correto é: "precisava que a classe que é instanciada premanecesse instanciada"

Desculpa o erro, sabe como é né, pressa!

Bom mesmo
publicado por <? Mr. Source Code ?> - 2004-10-04 18:19:31

Muito interessante estes novos recursos do php 5, melhorando um pouco os "furos" da orientação a objeto das versões anteriores. Mas uma questão: o php 5 resolveu aqueles problemas de cópias que eram feitas de objetos? pois se me lembro bem, precisávamos utilizar o operador '&' para evitar cópias.
Aquele manual pro php que tem no php.net ainda naum foi atualizado, se naum me engano... precisamos mais dissu

Dica:
publicado por Felipe Lunardi Farias - 2004-10-05 11:56:25

Leia esse pequeno manual, fala alguma coisa sobre cópias em objetos:
http://www.developer.com/lang/php/article.php/10941_3302171_1

observação
publicado por Thomas Gonzalez Miranda - 2004-10-06 07:41:06

na verdade, esta classe não precisa de mais do que um IF para funcionar, para se ter idéia, qualquer chamada que à new Vectra(), new Gol(), não vai resultar em nada pois a as funções da classe é chamada estaticamente, veja o novo exemplo de como a classe final poderia funcionar.

--
Final Class CarroFactory {
public static function GetCarro($TCarro) {
if (!$TCarro) {
return null;
} else {
return new $TCarro();
}
}
}

Header("Content-type: text/plain\n\n");

$Carro = "Gol";
print $Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->getPreco() );

print("\n\n");

$Carro = "Vectra";
print $Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->getPreco() );
--

Thomaz...
publicado por Felipe Lunardi Farias - 2004-10-06 08:17:08

Amigo, beleza. Eu sei que funcionaria perfeitamente. Porém, a idéia inicial dos artigos publicados aqui é ensina e não enxugar o código fonte.

re: Thomaz
publicado por Thomas Gonzalez Miranda - 2004-10-06 11:39:58

não tem nada de enxugação de código você que está ensinando algo que é desnecessário de se fazer.

re: re: Thomaz
publicado por Augusto Costa - 2004-10-06 16:35:03

Senhores,
desculpem por eu me intrometer, mas...
Felipe: O cara só está adicionando algo ao seu artigo, que por sinal está muito bom! Você ensinou de uma forma e Thomas está mostrando um outro meio de chegar ao mesmo lugar.

Thomas: Nada é desnecessário. A forma que você mostrou funciona muito bem com o exemplo dado por Felipe. Mas se as classes dos carros tivessem nomes diferentes do valor passado por parâmetro para o método GetCarro()? Será que funcionaria? Por exemplo:

//Notem que o nome da classe não é mais "Gol"
Class CarroGol extends Carro {
public function Gol() {
return $this->valor = 20000;
}
}

$Carro = "Gol";
print $Carro." - R$ " . ( CarroFactory::GetCarro($Carro)->getPreco() )

Acho que neste caso realmente seria necessário o uso dos "ifs".

Eu de novo...HEHE
publicado por Felipe Lunardi Farias - 2004-10-07 00:00:29

Amigos, só quero que saibam que o que pode ser fácil para uns pode ser difícil para outros... quero atingir a todos os níveis desde o iniciante ao avançado por isso estou tentando explicar não de forma simplificada mas sim de uma forma fácil de se aprender...ainda mais de orientação objeto que é onde fica as maiores dúvidas. Um abraço.

Bem Interessante
publicado por Rafael Ferreira Silva - 2004-10-23 23:29:40

Olá Felipe,

Parabéns pelo seu artigo ficou muito bom e bem didático. Gostei muito.

Quanto ao pequeno perrengue aí, eu acho q vale a pena mostrar como fazer(tanto de um modo como do outro).

Só uma nota: OO é muito boa e deve ser usada, mas a economia que se tem com ela é mais aproveitada em projetos grandes.
Obviamente o exemplo do Felipe é pequeno e faz as coisas ficarem mais complicadas, mas como ele disse, é para ser didático e não enxuto ehehe.

Abraços e parabéns novamente.

Re: Bom Mesmo
publicado por leassis - 2004-11-19 12:55:39

Respondendo e perguntando :-) ao amigo Reinaldo Martinez Cabral, o correto é o php retornar 35000 que eh o preco do golf neh?

o que está retornando? não entendi o seu topico..

se vc pedir para realizar soma dos dois valores... do jeito q vc exemplificou está errado...

pq vc nao vai conseguir criar uma instancia da classe abstrata... logo toda vez q vc chamar o metodo vai somar 0 ao valor do carro atual

Bem legal!
publicado por Felipe Lopes - 2004-12-22 09:19:52

Me deixou um pouco confuso porque ainda naum estou mto acostumado a esses static e abstract, mas foi muito interessante o artigo mesmo!

No problema do Reinaldo, eu não atribuiria um valor diretamente a $valor como está sendo feito...Criaria um método setValor para isso e dentro dele incrementaria o $valor a um atributo novo, valorTotal digamos...

entao seria:

public function setValor($valor){
$this->valor = $valor;
$this->valorTotal += $valor;
}

Ou algo assim...Aih as classes subsequentes ficariam algo como:


Class Golf extends Carro {
public function Golf() {
return $this->setValor(35000);
}
}

factory compartilhada
publicado por xDeCo - 2005-01-26 14:33:32

Algum tempo atras eu tinha criado uma factory para o gerenciamento dos objetos compartilhados, como o obj de DB, controladores, obj de Template, etc...
Dessa forma vc só precisaria instanciar a classe na hora que fosse realmente usar, evitando validaçoes para ver se tal objeto ja foi criado ou evitando criar objetos no inicio, que nem chegam a ser usados por fluxos alternativos ou de exceção.

<?php

class Factory
{
private $objects;

public function __construct()
{
$this->objects = array();
}

/*
objetos compartilhados
retorna o objeto da cache ou um novo caso ele nao tenha sido instanciado
@param $pack caminho do arquivo
ex: $user = $fac->get('cadastro/User.php');
*/
public function get($pack)
{
// se tem na cache
if ( array_key_exists( &$pack, &$this->objects ) )
{
return $this->objects[$pack];
}
// se nao tem instancia
else
{
$obj = $this->getNew(&$pack);
$this->objects[$pack] = $obj;
return $obj;
}
}

/*
instancia um objeto mas nao coloca na cache
ideal para objetos nao compartilhados
*/
public function getNew($pack)
{
if ( file_exists($pack) )
{
include_once($pack);
$class = basename($pack,'.php');
return new $class();
}
else
{
/*
aqui poderia ser um throw
mas seria um saco ter que um usar try para toda vez que fosse
chamar uma classe em projetos que vc sabe que ela existe
*/
return NULL;
}
}


}

?>

Exemplo de uso
<?php

$fac = new Factory();
$db = $fac->get("/persistencia/DB.php");

?>

If desnecessário
publicado por Juan Maiz Lulkin Flores da Cun - 2005-02-10 12:17:17

Caros,

O if neste exemplo é desencessário, podendo utilizar a variável como o nome da instância a ser criada.

Além disso a utilização de if's gera um problema na engenharia do software, que ocorre quando criamos uma nova classe e temos q ficar adicionando em todos os pontos.

Fui,
Maiz

Publique os seus Comentários

Nome:
Email:
Título:
Comentário:

NOTA: Cadastre-se no site para poder publicar comentários.

 
webmaster: João Prado Maia   © 2000 - 2005 phpbrasil.com
Gerado em 1.273 segundos