Série Design Patterns com PHP: I I- Factory
Vou tentar tornar este artigo bastante prático, para isso iremos criar uma interface e algumas classes.
A interface abaixo será implementa por algumas classes posteriormente.
Portanto, supondo que exista a interface IBanco:
A interface IBanco define o método connect() que deverá ser comum a todas as classes que a implementarem.
Vamos agora, criar mais três classes:
A primeira será a classe BancoMysql que será responsável pela comunicação com o SGBDR mySQL, a segunda será a classe BancoPostgres, que será responsável pela comunicação com o SGBDR PostgreSQL e por fim, a classe BancoOracle, que se comunicará com o SGBDR ORACLE.
BancoMysql.php:
BancoPostgres.php:
BancoOracle.php:
Utilizamos a palavra reservada implements para informar que as classes acima implementam a interface IBanco.
Agora vamos criar a classe Factory que nos retornará um objeto de uma dessas classes sem que o usuário que está utilizando estas classes precise saber o nome real da classe.
Vejamos então a implementação desta classe:
Na classe acima, de acordo com o parâmetro passado, é retornada uma instância de sua classe respectiva e se um dia houver uma mudança qualquer, por exemplo no nome da classe, você só precisará mudar em um lugar, na classe Factory.
Agora vamos executar esta classe:
Espero que este artigo tenha ajudado a esclarecer sobre o pattern Factory.
adler medrado
http://adler.neshertech.net
adler@neshertech.net
Referências:
PDO – Foi utilizado PDO para criar objetos referentes a cada banco.
http://www.php.net/pdo
A interface abaixo será implementa por algumas classes posteriormente.
Portanto, supondo que exista a interface IBanco:
<?php Interface IBanco { public function connect(); } ?>
A interface IBanco define o método connect() que deverá ser comum a todas as classes que a implementarem.
Vamos agora, criar mais três classes:
A primeira será a classe BancoMysql que será responsável pela comunicação com o SGBDR mySQL, a segunda será a classe BancoPostgres, que será responsável pela comunicação com o SGBDR PostgreSQL e por fim, a classe BancoOracle, que se comunicará com o SGBDR ORACLE.
BancoMysql.php:
<?php include_once ‘Ibanco.php’; class BancoMysql() implements IBanco { public function connect() { return new PDO('mysql:host=localhost;dbname=banco','root',''); } } ?>
BancoPostgres.php:
<?php include_once ‘Ibanco.php’; class BancoPostgres() implements IBanco { public function connect() { return new PDO('pgsql:host=localhost port=5432 dbname=banco user=username password=senha '); } } ?>
BancoOracle.php:
<?php include_once ‘Ibanco.php’; class BancoOracle() implements IBanco { public function connect() { return new PDO(’OCI:dbname=accounts;charset=UTF-8′, ‘username’, ’senha’); } } ?>
Utilizamos a palavra reservada implements para informar que as classes acima implementam a interface IBanco.
Agora vamos criar a classe Factory que nos retornará um objeto de uma dessas classes sem que o usuário que está utilizando estas classes precise saber o nome real da classe.
Vejamos então a implementação desta classe:
<?php include_once ‘BancoMysql.php’; include_once ‘BancoPostgres.php’; include_once ‘BancoOracle.php’; class BancoFactory { public function factory($banco) { switch ($banco) { case “mysql”: return new BancoMysql(); break; case “postgres”: return new BancoMysql(); break; case “oracle”: return new BancoMysql(); break; } } } ?>
Na classe acima, de acordo com o parâmetro passado, é retornada uma instância de sua classe respectiva e se um dia houver uma mudança qualquer, por exemplo no nome da classe, você só precisará mudar em um lugar, na classe Factory.
Agora vamos executar esta classe:
<?php include_once ‘BancoFactory.php’; $bancoFactory = new BancoFactory(); // Criando instância da classe BancoMysql $connMysql = $bancoFactory->factory(“mysql”); print_r($connMysql->connect()); // Criando instância da classe BancoPostgres $connPostgres = $bancoFactory->factory(“postgres”); print_r($connPostgres->connect()); // Criando instância da classe BancoOracle $connOracle = $bancoFactory->factory(“oracle”); print_r($connOracle->connect()); ?>
Espero que este artigo tenha ajudado a esclarecer sobre o pattern Factory.
adler medrado
http://adler.neshertech.net
adler@neshertech.net
Referências:
PDO – Foi utilizado PDO para criar objetos referentes a cada banco.
http://www.php.net/pdo
Páginas:
1
2
Olá a todos.
Primeiramente, agradeço a todos pelas manifestações.
Bom vamos lá.
Matheus, realmente no switch existe um erro. Em cada opção do bloco switch deve ser instânciada a classe referente ao banco desejado.
Apesar de rever o artigo antes de publicar este erro passou despercebido. Desculpe.
Sobre a implementação da interface em cada classe, é necessário porque cada classe precisa implementar os métodos contidos naquela interface. O erro ocorreria se você não implementasse algum método contido na interface na classe de banco.
Espero ter ajudado.
adler medrado
http://adler.neshertech.net
adler@neshertech.net
Primeiramente, agradeço a todos pelas manifestações.
Bom vamos lá.
Matheus, realmente no switch existe um erro. Em cada opção do bloco switch deve ser instânciada a classe referente ao banco desejado.
Apesar de rever o artigo antes de publicar este erro passou despercebido. Desculpe.
Sobre a implementação da interface em cada classe, é necessário porque cada classe precisa implementar os métodos contidos naquela interface. O erro ocorreria se você não implementasse algum método contido na interface na classe de banco.
Espero ter ajudado.
adler medrado
http://adler.neshertech.net
adler@neshertech.net
18/09/2006 11:08am
(~18 anos atrás)
Adler,
Primeiramente quero parabeniza-lo pelo grande apoio que esta dando a todos postando essas matérias sobre Designer Patterns. É uma grande vantagem saber sobre os Padrões de Designer de Software. O mercado exige muito em relação essa abordagem e particularmente está acrescentando bastante conhecimento a minha pessoa.
Tenho algumas duvidas em relação ao seu código de exemplo do Factory.
Porque devo implementar a interface IBanco em todas as classes de conexão? A classe BancoFactory geraria um erro ao instanciá-la não estando as classes de conexão com as interfaces implementadas?
Também não entendi porque que no switch da classe BancoFactory é instanciado, independente do case, sempre o objeto BancoMysql() e não os outros objetos referentes a classes de conexão com outros Bancos de Dados, ou seja, porque que no case "oracle" não foi instanciado o objeto BancoOracle referente a classe de Conexão com o banco Oracle? O código não esta errado?
Aguardo sua resposta. =)
Primeiramente quero parabeniza-lo pelo grande apoio que esta dando a todos postando essas matérias sobre Designer Patterns. É uma grande vantagem saber sobre os Padrões de Designer de Software. O mercado exige muito em relação essa abordagem e particularmente está acrescentando bastante conhecimento a minha pessoa.
Tenho algumas duvidas em relação ao seu código de exemplo do Factory.
Porque devo implementar a interface IBanco em todas as classes de conexão? A classe BancoFactory geraria um erro ao instanciá-la não estando as classes de conexão com as interfaces implementadas?
Também não entendi porque que no switch da classe BancoFactory é instanciado, independente do case, sempre o objeto BancoMysql() e não os outros objetos referentes a classes de conexão com outros Bancos de Dados, ou seja, porque que no case "oracle" não foi instanciado o objeto BancoOracle referente a classe de Conexão com o banco Oracle? O código não esta errado?
Aguardo sua resposta. =)
18/09/2006 10:38am
(~18 anos atrás)
Olá Adler,
Trabalho com design patterns há algum tempo e achei interessante sua série, porém gostaria de relatar bem resumidamente como os implemento:
No meu pacote de conexão com banco de dados, implementei o factory mas de uma forma diferente.
Criei uma classe base chamada Conexao que tinha a declaração 'implements' da interface IConexao, a partir daí todas as classes que herdavam a classe Conexao, ou seja Mysql, Postgresql e Oracle é quem realmente implementam os métodos dessa interface, mesmo não tendo a declaração implements, forçando a toda classe que herda de Conexao a implementar os métodos da sua interface, um verdadeiro contrato.
Dentro das classes filhas tenho o método singleton() e o padrão Factory retorna o singleton de cada classe.
Ex.: case 'Mysql' : return Mysql::singleton(); break;
Espero ter contribuído com seu artigo.
Abraço!
Trabalho com design patterns há algum tempo e achei interessante sua série, porém gostaria de relatar bem resumidamente como os implemento:
No meu pacote de conexão com banco de dados, implementei o factory mas de uma forma diferente.
Criei uma classe base chamada Conexao que tinha a declaração 'implements' da interface IConexao, a partir daí todas as classes que herdavam a classe Conexao, ou seja Mysql, Postgresql e Oracle é quem realmente implementam os métodos dessa interface, mesmo não tendo a declaração implements, forçando a toda classe que herda de Conexao a implementar os métodos da sua interface, um verdadeiro contrato.
Dentro das classes filhas tenho o método singleton() e o padrão Factory retorna o singleton de cada classe.
Ex.: case 'Mysql' : return Mysql::singleton(); break;
Espero ter contribuído com seu artigo.
Abraço!
12/09/2006 7:09am
(~18 anos atrás)
E isso aí Mark, o __autoload() é um ótimo recurso para nos livrar dos problemáticos includes.
referência: http://www.php.net/manual/pt_BR/language.oop5.autoload.php
Escreva o artigo sim, vale à pena explorar a boa implementação dos recursos do PHP 5.
Também estou preparando um artigo para o iMasters sobre implementação do MVC no PHP, com base numa framework que desenvolvemos e está começando a ser utilizada no governo, muito interessante.
referência: http://www.php.net/manual/pt_BR/language.oop5.autoload.php
Escreva o artigo sim, vale à pena explorar a boa implementação dos recursos do PHP 5.
Também estou preparando um artigo para o iMasters sobre implementação do MVC no PHP, com base numa framework que desenvolvemos e está começando a ser utilizada no governo, muito interessante.
06/09/2006 6:21pm
(~18 anos atrás)
Olá, Adler, ultimamente eu criei uma classe para banco bem parecida, não sei muito a nomenclatura dos termos, mas é basicamente o que fez, só que utilizei alguns outros recursos:
eu criei um diretório chamado plugins, onde eu guardo as classes para os bancos(postgres, mysql, mssql...), tenho a interface, e a classe mgBanco, onde eu seleciono o banco correto, foi aí que eu mudei: não coloquei todos os includes, como plugins eu tenho: "mysql.php", "postgres.php", "mssql.php"..., quando vou instanciar eu instancio da seguinte forma:
------------
function conect()
{
$tipo = $CONFIG['type'];//aqui é passado mysql, postgres, mssql...
$conexao = new $tipo()
}
------------
na variável tipo eu tenho a classe a ser chamada, o segredo está em ser usada a função "__autoload", esta função é disparada quando o php tenta instanciar uma classe que não está inclusa:
------------
function __autoload($class_name) {
$nome = strtolower($class_name);
require_once("plugins/".$nome.".php");
}
------------
assim ele inclui somente a classe necessária para o momento...
estava até querendo fazer um artigo para esta minha classe...
até mais.
eu criei um diretório chamado plugins, onde eu guardo as classes para os bancos(postgres, mysql, mssql...), tenho a interface, e a classe mgBanco, onde eu seleciono o banco correto, foi aí que eu mudei: não coloquei todos os includes, como plugins eu tenho: "mysql.php", "postgres.php", "mssql.php"..., quando vou instanciar eu instancio da seguinte forma:
------------
function conect()
{
$tipo = $CONFIG['type'];//aqui é passado mysql, postgres, mssql...
$conexao = new $tipo()
}
------------
na variável tipo eu tenho a classe a ser chamada, o segredo está em ser usada a função "__autoload", esta função é disparada quando o php tenta instanciar uma classe que não está inclusa:
------------
function __autoload($class_name) {
$nome = strtolower($class_name);
require_once("plugins/".$nome.".php");
}
------------
assim ele inclui somente a classe necessária para o momento...
estava até querendo fazer um artigo para esta minha classe...
até mais.
04/09/2006 5:54am
(~18 anos atrás)
Tenho uma consultoria que atende empresas em toda a América Latina, tenho como principais clientes a Alcatel e a Ford. Uma das principais ferramentas de minha empresa é baseada em PHP/MySQL (http://www.workforcesys.com) e minha empresa precisa a cada venda de um profissional para customizá-la. Enviem seus CV's para:
marcelo.veras@workforcesys.com
Não importa o estado onde vc more (temos projetos no Brasil todo e para fora do Brasil inclusive)
É importante possuir alguma experiência em implementação de sistemas de gestão e habilidade para aplicar treinamentos aos usuários. Desejável disponibilidade para viagens.