Back-End

13 out, 2011

Diferença de implementação de um diagrama de classes: “Composição X Agregação”

Publicidade

Há algum tempo escrevi um artigo mostrando a diferença de representação UML no relacionamento entre classes: Composição X Agregação.

Neste artigo mostrarei a diferença na implementação do código para as duas situações. Para isso precisamos reforçar alguns conceitos do ponto de vista de programação, já que no artigo anterior, os conceitos passados foram do ponto de vista da análise de sistema.

A diferença entre a agregação e a composição é que na primeira (agregação) o Objeto-Todo poderá utilizar funcionalidades do objeto agregado (Objeto-Parte). Já na composição, o Objeto-Todo será responsável pela criação e destruição do Objeto-Parte, assim, o Objeto-Todo realmente terá instâncias do Objeto-Parte. (Dall’Ogilo, 2009, pg 118 a 124)

Para entender melhor isso, vamos exemplificar, utilizando as mesmas classes do artigo anterior, começando pela agregação.

class Time {

protected $nomeTime;
protected $tecnico;
protected $atletas = array();

function __construct($nomeTime, $nomeTecnico)
{
$this->setNomeTime($nomeTime);
$this->setTecnico($nomeTecnico);
}

public function getNomeTime()
{
return $this->nomeTime;
}

public function setNomeTime($nomeTime)
{
$this->nomeTime = $nomeTime;
}

public function getTecnico()
{
return $this->tecnico;
}

public function setTecnico($tecnico)
{
$this->tecnico = $tecnico;
}

public function getAtletas()
{
return $this->atletas;
}

public function setAtletas($atletas)
{
$this->atletas = $atletas;
}

function addAtleta(Atleta $atleta)
{
$this->atletas[] = $atleta;
}

function mostrarTime()
{
foreach ($this->atletas as $atleta)
{
$atl[] = $atleta->getAtleta();
}
echo '<pre>';
echo 'Nome do time: ' . $this->nomeTime;
echo '<br>';
echo 'Nome do tecnico: ' . $this->tecnico;
echo '<br>';
print_r($atl);
echo '</pre>';
}

}

class Atleta {

var $nomeAtleta;
var $idade;
var $posicao;

function __construct($nomeAtleta, $idade, $posicao)
{
$this->setNomeAtleta($nomeAtleta);
$this->setIdade($idade);
$this->setPosicao($posicao);
}

function setNomeAtleta($nomeAtleta)
{
$this->nomeAtleta = $nomeAtleta;
}

function setIdade($idade)
{
$this->idade = $idade;
}

function setPosicao($posicao)
{
$this->posicao = $posicao;
}

function getAtleta()
{
return array('nome_atleta' => $this->nomeAtleta,
'idade' => $this->idade,
'posicao' => $this->posicao);
}

}

//Instancia o objeto
$time = new Time('Itapipoca FC', 'Seu Creiton');

//Adiciona os atletas ao time
$time->addAtleta(new Atleta('Pedro', 15, 'Meio Campo'));
$time->addAtleta(new Atleta('Paulo', 14, 'Atacante'));
$time->addAtleta(new Atleta('Joao', 15, 'Zagueiro'));
$time->addAtleta(new Atleta('Carlos', 15, 'Goleiro'));

//Mostra a escalacao do time
$time->mostrarTime();

Como demonstrado nesta codificação, o Objeto-Parte é completamente independente do Objeto-Todo. O Objeto-Parte já é passado instanciado para o Objeto-Todo: “Atleta” é passado instanciado para “Time”. Isso demonstra claramente que o Objeto-Parte (Atleta) existe mesmo que o Objeto-Todo (Time) não exista.

Já na Composição, o Objeto-Todo é responsável pela criação e manipulação do Objeto-Parte. Vamos ao exemplo:

class ItemPedido
{

protected $codigo;
protected $descricao;
protected $quantidade;
protected $valorUnitario;

function __construct($codigo, $descricao, $quantidade, $valorUnitario)
{
$this->setCodigo($codigo);
$this->setDescricao($descricao);
$this->setQuantidade($quantidade);
$this->setValorUnitario($valorUnitario);
}

public function getCodigo()
{
return $this->codigo;
}

public function setCodigo($codigo)
{
$this->codigo = $codigo;
}

public function getDescricao()
{
return $this->descricao;
}

public function setDescricao($descricao)
{
$this->descricao = $descricao;
}

public function getQuantidade()
{
return $this->quantidade;
}

public function setQuantidade($quantidade)
{
$this->quantidade = $quantidade;
}

public function getValorUnitario()
{
return $this->valorUnitario;
}

public function setValorUnitario($valorUnitario)
{
$this->valorUnitario = $valorUnitario;
}

}

class Pedido
{

protected $numeroPedido;
protected $cliente;
protected $itensPedido = array();

function __construct($numeroPedido, $cliente)
{
$this->numeroPedido = $numeroPedido;
$this->cliente = $cliente;
}
public function setItensPedido($itensPedido)
{
$this->itensPedido = $itensPedido;
}

function setNumeroPedido($numeroPedido)
{
$this->numeroPedido = $numeroPedido;
}

public function getItensPedido()
{
return $this->itensPedido;
}

function getNumeroPedido()
{
return $this->numeroPedido;
}

function setCliente($cliente)
{
$this->cliente = $cliente;
}

function getCliente()
{
return $this->cliente;
}

function adicionarItens($codigo, $descricao, $quantidade, $valorUnitario)
{
$itemPedido = new ItemPedido($codigo, $descricao, $quantidade, $valorUnitario);

$codigo = $itemPedido->getCodigo();

//Verifica se ja existe o item no pedido, se tiver, apenas soma a quantidade
//para que nao fiquem itens duplicados
if (key_exists($codigo, $this->itensPedido))
{
$this->itensPedido[$codigo]['QUANTIDADE'] += $itemPedido->getQuantidade();
}
else
{
$this->itensPedido[$codigo]['DESCRICAO'] = $itemPedido->getDescricao();
$this->itensPedido[$codigo]['QUANTIDADE'] = $itemPedido->getQuantidade();
$this->itensPedido[$codigo]['VLR_UNITARIO'] = $itemPedido->getValorUnitario();
}
}

function mostrarPedido()
{
echo '<pre>';
echo 'Número Pedido: ' . $this->getNumeroPedido();
echo '<br>';
echo 'Cliente: ' . $this->getCliente();
echo '<br>';
echo 'Itens do pedido:';
echo '<br>';
foreach ($this->itensPedido as $codigoProduto => $dadosProduto)
{
echo '&nbsp&nbsp Código: ' . $codigoProduto . '<br>';
echo '&nbsp&nbsp Descricao: ' . $dadosProduto['DESCRICAO'] . '<br>';
echo '&nbsp&nbsp Quantidade: ' . $dadosProduto['QUANTIDADE'] . '<br>';
echo '&nbsp&nbsp Valor Unitário: ' . $dadosProduto['VLR_UNITARIO'] . '<br>';
echo '&nbsp&nbsp Sub Total: ' . $dadosProduto['VLR_UNITARIO'] * $dadosProduto['QUANTIDADE'] . '<br>';
echo '&nbsp&nbsp --------------------------------------<br>';
}
echo '</pre>';
}

}

//Instancia o objeto
$pedido = new Pedido(123, 'Cliente 001');

//Adiciona itens ao pedido
$pedido->adicionarItens('951', 'PenDrive 512Mb', 3, 55);
$pedido->adicionarItens('952', 'PenDrive 256Mb', 3, 35);
//Adiciono um item repetido, para testar a funcao que soma
//a quantidade no item ja esxistente
$pedido->adicionarItens('951', 'PenDrive 512Mb', 3, 55);

//Mostra o pedido
$pedido->mostrarPedido();

Vejam que no método “adicionarItens()”, diferentemente do exemplo anterior, não
é passado para o método uma variável do tipo “itemPedido”, mas sim
os dados do item, para que o próprio método possa instanciar e
manipular a classe ItemPedido.

Espero que ajude. Até o próximo!

Bibliografia

Dall’Ogilo, Pablo: PHP: Programando com orientação a objetos. 2. Ed., São Paulo: Novatec Editora, 2009.