sexta-feira, 29 de outubro de 2010

Design Patterns (PHP) - Strategy

Strategy

Nesse padrão, os algoritmos são extraídos de classes complexas para que eles possam ser facilmente substituidos.

Objetivos:

  • Definir uma família de algoritmos, encapsular cada um, e torná-los intercambiáveis
  • Strategy permite mudar os algoritmos independentemente dos clientes que os usam

Use Strategy quando:

  • Várias classes relacionadas diferem apenas em seus comportamentos. Strategy proporciona um modo de configurar uma classe com um de muitos comportamentos.
  • Você precisa de diferentes variantes de um algoritmo.
  • Uma classe define muitos comportamentos, e eles aparecem como múltiplas declarações condicionais nas suas operações. Ao invés de várias condições, mova desvios condicionais relacionados para sua propria classe Strategy.
Exemplo:

Para exemplificar a solução do problema apresentado no início do artigo, vamos criar a interface MeioTransporte, que representará todo e qualquer veículo capaz de transportar alguma coisa, com suas devidas implementações:


interface MeioTransporte
{
public function transportar();
}

class Aviao implements MeioTransporte
{
public function transportar()
{
print('voando nos céus...');
}
}

class Carro implements MeioTransporte
{
public function transportar()
{
print('andando sobre a estrada...');
}
}

A partir dessa estrutura, já temos nossos diferentes algoritmos encarregados de conversar com o requisitante. Dessa forma, nosso método transportar() poderá se comportar da maneira que a aplicação decidir, sempre de acordo com a requisição feita pelo usuário.

Agora, sim, ao criarmos a abstração de Veículo, teremos uma estrutura pronta para determinar o fluxo da aplicação:

abstract class Veiculo
{

private $meioTransporte;
public function setMeioTransporte( MeioTransporte $meioTransporte )
{
$this
->meioTransporte = $meioTransporte;
}
public function transportar()
{
$this
->meioTransporte->transportar();
}
}

Depois de criarmos a abstração da classe Veículo, podemos criar os veículos em si, sem nos preocuparmos com a implementação do método transportar(), que já será manipulado pela estrutura que criamos anteriormente:

class Boeing extends Veiculo
{

public function __construct()
{
$this
->setMeioTransporte( new Aviao() );
}
}

class
Fusca extends Veiculo
{

public function __construct()
{
$this
->setMeioTransporte( new Carro() );
}
}

Com essa implementação do Strategy, garantimos a organização estrutural da nossa hierarquia, e permitimos que a aplicação manipule, da maneira que a estruturamos, como será o fluxo de sua resposta à requisição.

Se criarmos, agora, um objeto de cada tipo representado na implementação, e invocarmos o método transportar(), herdado por cada um da abstração de Veículo, da seguinte maneira:

$carro = new Carro();
$aviao
= new Aviao();
$carro
->transportar();
$aviao
->transportar();

Teríamos a seguinte saída:

andando sobre a estrada...
voando nos c
éus...


Design Patterns (PHP) - Factory

O que é design pattern?
São formas de se escrever código de programação utilizando conceitos de melhores práticas de programação que visam mostrar soluções para problemas comuns no desenvolvimento de software.

O que é o factory?
Basicamente, o pattern factory consiste em uma fábrica de objetos de classes que implementam uma mesma interface e quando precisamos de uma instância de uma destas classes, a factory nos retorna este objeto de forma dinâmica.

A interface abaixo será implementa por algumas classes posteriormente.

Supondo que exista a interface IBanco:

1.

2. Interface IBanco {

3. public function connect();

4. }

5.

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 mysql que será responsável pela comunicação com o SGBDR mySQL, a segunda será a classe postgres, que será responsável pela comunicação com o SGBDR PostgreSQL e por fim, a classe oracle, que se comunicará com o SGBDR ORACLE.

mysql.php:

1.

2. include_once ‘Ibanco.php’;

3. class mysql() implements IBanco {

4. public function connect() {

5. return new PDO('mysql:host=localhost;dbname=banco','root','');

6. }

7. }

8.

postgres.php:

1.

2. include_once ‘Ibanco.php’;

3.

4. class postgres() implements IBanco {

5. public function connect() {

6. return new PDO('pgsql:host=localhost port=5432 dbname=banco user=username password=senha ');

7. }

8. }

9.

oracle.php:

1.

2. include_once ‘Ibanco.php’;

3. class oracle() implements IBanco {

4. public function connect() {

5. return new PDO(’OCI:dbname=accounts;charset=UTF-8′, ‘username’, ’senha’‘);

6. }

7. }

8.

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:

1.

2. include_once ‘mysql.php’;

3. include_once ‘postgres.php’;

4. include_once ‘oracle.php’;

5.

6. class BancoFactory {

7. public function factory($banco) {

8. return new $banco();

9. }

10. }

Na classe acima, de acordo com o parâmetro passado ("mysql", "postgres" ou "oracle"), é 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:

1.

2. include_once ‘BancoFactory.php’;

3. $bancoFactory = new BancoFactory();

4.

5. // Criando instância da classe mysql

6. $connMysql = $bancoFactory->factory(mysql);

7. print_r($connMysql->connect());

8.

9. // Criando instância da classe postgres

10. $connPostgres = $bancoFactory->factory(“postgres”);

11. print_r($connPostgres->connect());

12.

13. // Criando instância da classe oracle

14. $connOracle = $bancoFactory->factory(“oracle”);

15. print_r($connOracle->connect());