quarta-feira, 28 de março de 2012

Curso de PHP Orientado a Objetos - Parte 8

Vamos iniciar o oitavo artigo do curso de PHP Orientado a Objetos do site www.cafeesoftware.com.

Para conhecer as demais partes, clique aqui.

Ao final deste artigo, você será capaz de:
  • Entender como se da a relação entre objetos
  • Entender quando se dá um relacionamento de associação, agregação e composição 

Imagem meramente ilustrativa

Em OO é comum que objetos se relacionem um com os outros para desempenhar suas tarefas. Neste tutorial veremos os tipos de relacionamentos existentes.

Associação: É a relação mais comum entre dois objetos. Quando acontece? Quando uma classe "usa" outra classe.
Exemplo: Um motorista utiliza (depende do carro, mas este não faz parte do motorista) o carro para trabalhar. 

Agregação: É o tipo de relação conhecida como todo/parte. Na agregação o objeto agrega outro objeto, ou seja, torna um objeto externo parte de si.. Assim o objeto pai poderá utilizar funcionalidades do objeto agregado, mas ele não depende dele (agregado) para existir.
Exemplo: A tampa de uma caneta é parte da caneta, se a caneta não tiver a tampa, ela não deixará de ser uma caneta.

Composição: Neste caso, o objeto-pai é responsável pela criação e destruição de suas partes. O objeto-pai realmente "possui" as instâncias de suas partes. Resumidamente, um só existe caso o outro também exista.
Exemplo: O motor de um carro é parte fundamental do carro.

Agora que você já conhece na teoria os tipos de relacionamento, que tal vermos na prática?

Associação

A forma mais comum de associação é quando temos um objeto como atributo de outro. Criaremos um objeto Produto e outro Fornecedor. Onde Fornecedor é um dos atributos de Produto.

Vamos analisar o diagrama UML:

Associação entre Produto e Fornecedor
Observe que uma das propriedades (Fornecedor), espera receber um objeto do tipo Fornecedor.

Vamos agora criar as duas classes e em seguida os objetos.

class Produto{

  public $Id;
  public $Nome;
  public $Valor;
  public $Fornecedor;

  public function __construct($Id, $Nome, $Valor, $Fornecedor){
    $this->Id = $Id;
    $this->Nome = $Nome;
    $this->Valor = $Valor;
    $this->Fornecedor = $Fornecedor;
  }

}

class Fornecedor{

  public $Id;
  public $RazaoSocial;
  public $Endereco;
  public $Telefone;

  public function __construct($Id, $RazaoSocial, $Endereco, $Telefone){
    $this->Id = $Id;
    $this->RazaoSocial = $RazaoSocial;
    $this->Endereco = $Endereco;
    $this->Telefone = $Telefone;
  }

}

$fornecedor = new Fornecedor(359, "Mercado da Casa", "Rua B", "3232-2222" );

$produto = new Produto(122, "Café 250g", 2.85, $fornecedor );

echo "Código: " . $produto->Codigo . "< br />";
echo "Produto: " . $produto->Nome . "< br />";
echo "Fornecedor: " . $produto->Fornecedor->RazaoSocial . "< br />";

Perceba que, ao criar o objeto Produto, passamos o objeto Fornecedor, em seguida, para imprimir fizemos uma referenciação de Produto e Fornecedor.

Agregação

Conforme visto anteriormente, esta relação se dá quando temos o "TODO/PARTE". 
Uma forma de exemplificar sua implementação e com o clássico exemplo de um carrinho de compras. 
Teremos duas classes, produto (bem parecido com a que vimos anteriormente) e a classe Carrinho.
Observe o diagrama:
Relação de Agregação
Importante destacar que a propriedade Itens é um array, poderia ser representando como: Itens[] : Produto.
Observer que a classe Carrinho possui dois métodos, ExibeLista() e o CalculaTotal().
Vamos criar codificar as duas classes e em seguida criar os objetos:


class Produto{

  public $Id;
  public $Nome;
  public $Valor;

  public function __construct($Id, $Nome, $Valor){
    $this->Id = $Id;
    $this->Nome = $Nome;
    $this->Valor = $Valor;
  }

}
Agora vamos criar a classe Carrinho:
class Carrinho{

  private $itens;

  public function InsereProduto(Produto $item){

    $this->itens[] = $item;

  }

  public function ExibeLista(){

    foreach( $this->itens as $item ){
      return $item->nome."< br />;
    }

  }

  public function CalculaTotal(){

    $valor_total = 0;

    foreach( $this->itens as $item ){
      $valor_total += $item->Valor;
    }

    echo " R$ " . number_format($valor_total, 2, ',', '.');

  }

}

Vamos as explicações: Repare que na linha 5 da classe Carrinho estamos obrigando o $item a ser do tipo Produto. Este é um conceito conhecido como TypeHinting ou "Sugestão de tipo", caso este método receba algo que não seja um Produto, ocasionará um erro.
Na linha 7 estamos inserindo cada produto no array $itens.
O método ExibeLista apenas percorre o array de itens exibindo o nome de cada produto.
O método CalculaTotal percorre o array de itens somando o valor de cada um e em seguida mostrando (formatado) o valor final.

Vamos testar?

$produto1 = new Produto(1, "Milho verde", 1.75);
$produto2 = new Produto(2, "Ervilha", 1.65);
$produto3 = new Produto(3, "Café 250Gr", 3.45);
$produto4 = new Produto(4, "Refrigerante 2L", 3.69);

$CarrinhoCompra = new Carrinho();
$CarrinhoCompra->InsereProduto($produto1);
$CarrinhoCompra->InsereProduto($produto2);
$CarrinhoCompra->InsereProduto($produto3);
$CarrinhoCompra->InsereProduto($produto4);

$CarrinhoCompra->ExibeLista();
$CarrinhoCompra->CalculaTotal();

Ao executar, você perceberá que a lista de itens (nome) será exibida, seguido do valor total.

Composição

A diferença da composição para a agregação é que quando o objeto "todo" é destruído, suas partes também são, exatamente por terem sido criadas pelo objeto "todo". Podemos dizer que na composição o objeto-pai "possui" as instâncias de suas partes.
Observe a notação para a composição:
Relação de Composição
Neste exemplo, a classe cliente será responsável por instanciar contato. Vamos agora codificar para entender melhor:

class Contato{

  public $Nome;
  public $Email;
  public $Telefone;

  /* Método setContato()
  *  Grava informações de contato
  */

  public function setContato($Nome, $Email, $Telefone){

    $this->Nome = $Nome;
    $this->Email = $Email;
    $this->Telefone = $Telefone;

  }

  /* Método EscreveContato()
  *  Escreve as informações de contato
  */

  public function EscreveContato(){

    echo "Nome: " . $this->Nome . "< br />";
    echo "Email: " . $this->Email . "< br />";
    echo "Telefone: " . $this->Telefone . "< br />";

  }

}
Agora vamos criar a classe Cliente:
class Cliente{

  public $Codigo;
  public $Endereco;
  public $Contato;

  /* Método construtor()
  *  Construtor da classe
  */

  public function __construct(){

    /* Instancia um novo Contato
    * Perceba que isso só é feito 
    * aqui. Não é feito fora dessa
    * classe
    */
 
    $this->Contato = new Contato();

  }

  /* Método setContato()
  *  Grava informações de contato
  */

  public function setContato($Nome, $Email, $Telefone){

    // Chama e envia informações para o objeto Contato
    $this->Contato->setContato($Nome, $Email, $Telefone);

  }

  /* Método EscreveContato()
  *  Escreve as informações de contato
  */

  public function EscreveContato(){

    // Chama um método do objeto Contato
    $this->Contato->EscreveContato();

  }

}


Perceba que a classe Cliente só existe se também existir a classe Contato. Uma aplicação clara da relação de composição. Vamos agora testar o exemplo:

$leandro = new Cliente();
$leandro->Codigo = 7;
$leandro->setContato("Leandro","leandrocastro@gmail.com","(33) 3333-3333");
$leandro->Endereco = "Rua 13 de maio";

$leandro->EscreveContato();
echo "Endereço: " . $leandro->Endereco;


Note que em nenhum momento instanciamos Contato, pois quem faz isso é a classe Cliente, daí a relação de composição.


Finalizamos assim mais um artigo do curso. 
Na próxima aula veremos os métodos __set(), __get() e __call() conhecidos como métodos interceptores. 
Utilize o espaço de comentários para críticas, sugestões ou elogios.

Nenhum comentário:

Postar um comentário