Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Carlos Adriano

Modelagem Pessoa - Pessoa Física - Pessoa Jurídica - Clientes

Recommended Posts

Boa noite pessoal, gostaria de pedir uma ajuda de vocês para modelar um sistema no qual estou desenvolvendo.

 

Tenho as seguintes classes

 

abstract class Pessoa

public class PessoaFisica extends Pessoa

public class PessoaJuridica extends Pessoa

 

Agora eu preciso criar uma classe de clientes, só que os clientes podem ser PF e PJ... como fazer isso?

 

É como se em determinado momento o cliente fosse PF e em outros momentos ele será PJ...

 

Estive procurando aqui no fórum e achei algumas idéias interessantes, no entanto, gostaria de pedir a vocês um exemplo prático nesse contexto que descrevi acima.

 

Pensei em criar uma classe ClientePF e outra ClientePJ, mas achei que não ficou muito legal.

 

A minha idéia é generalizar a classe Cliente...

o que deveria fazer? Criar uma composição de PF e PJ dentro de Cliente?

 

Por favor pessoal, me deem exemplos práticos ok?

Abraço a todos!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Se eu entendi corretamente acho que a melhor opção é utilizar o design patter "Single Table Inheritance", pois já que PF podem virar PJ e vice-versa, acho que a melhor escolha é esta.

De uma pesquisada sobre.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim entendi, só que Single Table Inheritance está relacionado a maneira que a gente vai fazer o mapeamento das entidades, certo?

 

Só que a minha dúvida talvez não seja a maneira de representar isso no SGBD mas sim, como trabalhar para aproveitar a classe cliente tanto para pessoa física quando para pessoa jurídica.

 

abstract class Pessoa{
  private $nome;
  private $endereco;
...
}

public class PessoaFisica extends Pessoa{
 private $cpf;
 private $rg;
}

public class PessoaJuridica extends Pessoa{
 private $cnpj;
 private $ie;
}

public class Cliente extends ???{
 private $Pessoa ???
 private $PF ???
 private $PJ ???
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Carlos Adriano,

 

Quando trabalhamos com orientação a objetos, a única forma de sabermos como trabalhar com um determinado objeto é através de sua interface.

 

Para se definir a interface de um objeto, primeiro precisamos analisar o que será comum para um grupo de objetos.

 

Tanto uma pessoa física quanto jurídica possuem:

 

1. 2 tipos de documentos

2. Nome

3. Endereço (bairro, cep, cidade, ...)

4. Um tipo (PF ou PJ)

 

Para simplificar, vou pular a definição do endereço:

 

interface IPessoa {
const PESSOA_FISICA		= 1;
const PESSOA_JURIDICA	= 2;

public function getDoc1();
public function getDoc2();
public function getNome();
public function getTipo();

public function mostra();

public function setDoc1( $doc1 );
public function setDoc2( $doc2 );
public function setNome( $nome );
}

 

Com a interface IPessoa definida dessa forma, podemos criar uma classe concreta PessoaFisica da seguinte forma:

class PessoaFisica implements IPessoa {
protected $doc1;
protected $doc2;
protected $nome;
protected $tipo = self::PESSOA_FISICA;

public function getDoc1(){
	return $this->doc1;
}

public function getDoc2(){
	return $this->doc2;
}

public function getNome(){
	return $this->nome;
}

public function getTipo(){
	return $this->tipo;
}

public function mostra(){
	echo 'Pessoa fisica ' , $this->getNome() , PHP_EOL;
}

public function setDoc1( $doc1 ){
	$this->doc1 =& $doc1;
}

public function setDoc2( $doc2 ){
	$this->doc2 =& $doc2;
}

public function setNome( $nome ){
	$this->nome =& $nome;
}
}

 

O problema é que, se você tiver um comportamento para PessoaFisica e outro diferente para PessoaJuridica você poderá ter problemas, nesse caso, a definição pode ser assim:

 

abstract class AbstractPessoa implements IPessoa {
protected $doc1;
protected $doc2;
protected $nome;
protected $tipo;

final public function __construct( $nome , $doc1 , $doc2 ){
	if ( $this->tipo == null ) throw new RuntimeException( 'É preciso definir o tipo da pessoa' );
	else {
		$this->setNome( $nome );
		$this->setDoc1( $doc1 );
		$this->setDoc2( $doc2 );
	}
}

public function getDoc1(){
	return $this->doc1;
}

public function getDoc2(){
	return $this->doc2;
}

public function getNome(){
	return $this->nome;
}

public function getTipo(){
	return $this->tipo;
}

public function setDoc1( $doc1 ){
	$this->doc1 =& $doc1;
}

public function setDoc2( $doc2 ){
	$this->doc2 =& $doc2;
}

public function setNome( $nome ){
	$this->nome =& $nome;
}
}

 

Com a definição dessa forma, deixamos para as PF e PJ apenas a definição do método mostra() que é específico para cada uma:

class PessoaFisica extends AbstractPessoa {
protected $tipo = self::PESSOA_FISICA;

public function mostra(){
	echo 'Pessoa fisica ' , $this->getNome() , PHP_EOL;
}
}

 

E para PessoaJuridica:

class PessoaJuridica extends AbstractPessoa {
protected $tipo = self::PESSOA_JURIDICA;
private $socios = array();

public function adicionaSocio( PessoaFisica $socio ){
	$this->socios[] =& $socio;
}

public function getSociosIterator(){
	return new ArrayIterator( $this->socios );
}

public function mostra(){
	$iterator = $this->getSociosIterator();

	echo 'Pessoa jurídica ' , $this->getNome() , PHP_EOL;

	if ( $iterator->count() ){
		echo 'Listando sócios: ' , PHP_EOL;

		foreach ( $iterator as $socio ){
			$socio->mostra();
		}
	}
}
}

 

Como as duas classes implementam a interface IPessoa, a classe Cliente poderá aceitar apenas esse tipo de objeto:

class Cliente {
public function setPessoa( IPessoa $pessoa ){
	echo 'Definindo o cliente: ';
	$pessoa->mostra();
}
}

 

Dessa forma, podemos definir um cliente como Pessoa Física:

$fulano = new PessoaFisica( 'Fulano' , '123' , '456' );
$cliente = new Cliente();
$cliente->setPessoa( $fulano );

 

A saída será:

Definindo o cliente: Pessoa fisica Fulano

 

Ou uma Pessoa Jurídica:

$empresax = new PessoaJuridica( 'Empresa X' , '9999' , '8888' );

$cliente = new Cliente();
$cliente->setPessoa( $empresax );

 

Saída:

Definindo o cliente: Pessoa jurídica Empresa X

 

E ainda uma Pessoa Jurídica com alguns sócios que são Pessoas Física:

$fulano = new PessoaFisica( 'Fulano' , '123' , '456' );
$sicrano = new PessoaFisica( 'Sicrano' , '000' , '111' );

$empresax = new PessoaJuridica( 'Empresa X' , '9999' , '8888' );
$empresax->adicionaSocio( $fulano );
$empresax->adicionaSocio( $sicrano );

$cliente = new Cliente();
$cliente->setPessoa( $empresax );

 

Saída:

Definindo o cliente: Pessoa jurídica Empresa X

Listando sócios:

Pessoa fisica Fulano

Pessoa fisica Sicrano

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.