Modelagem Cliente - Fornecedor

6 respostas
celso.martins

Boa tarde,

Não sei se estou no fórum certo, mas como esse fala em “arquitetura de sistemas”, vamos lá.

Gostaria de saber como modelar um sistema “fornecedor de serviço - cliente”. Por exemplo: Aqui está a modelagem que estou usando.

Classe abstrata Agente;

Classe PJ É UM Agente;

Classe PF É UM Agente;

Cliente PODE SER um PF ou PODE SER um PJ;

Classe Atendimento TEM UM Cliente;

Pois é… a dúvida é essa: Como modelar essa classe Cliente que pode ser PJ ou PF. Pensei em criar a classe Cliente com atributos PF e PJ e quem não estivesse nulo “ditaria” quem é esse “cara”. Entretanto achei essa solução meio porca (posso estar redondamente errado, devido a minha inexperiência). Outra solução que imaginei foi colocar em Atendimento as classes ClientePJ e ClientePF, se comportando da mesma forma explicada anteriormente. Mas também não vi com bons olhos essa solução.

As operações são iguais. PF e PJ diferem apenas pelos atributos que definem as documentações(CPF, CNPJ, RG, etc). Essas informações serão importantes para relatórios, contato e notas fiscais.

Então companheiros de Jornada Javaneira, ou melhor, UMLeira, como fazer?

Agradeço antecipadamente.
Celso Martins

6 Respostas

king_of_gods

Eu recomendaria vc usar uma classe Identificação, uma classe PF e outra classe PJ. A jogada é, dentro da classe identificação você teria dois metodos praticamente iguais, onde um te retorna a pessoa fisica e no outro a pessoa juridica.

king_of_gods

Celso da uma lida sobre polimorfismo. http://pt.wikipedia.org/wiki/Polimorfismo

celso.martins

Obrigado pela resposta.

Deixa ver se eu entendi.

Na classe Cliente eu teria uma referência a uma classe chamada Identificacao. Essa classe Identificacao teria os metodos getPF() e getPJ(), é isso?

Se eu entendi, o problema da classe Cliente não “saber” se é PF ou PJ continua.

Entretanto acredito que o teu exemplo tenha ajudado bastante, se eu implementar na classe Identificacao apenas um método, getPessoa():Object. Assim esta classe varreria as tabelas de PF e PJ a procura da PK de Agente. Dessa forma, devolveria uma instancia de PF ou PJ. Será que isso comprometeria muito a perfomance? Algo como:

SELECT * FROM pf WHERE pfage = ?

if Empty {
  SELECT * FROM pj WHERE pjage = ?
}

Assim, surge outra dúvida na minha limitada mente. Como eu faria o casting para PF ou PJ? Posso “perguntar” ao objeto se ele é “instanceOf” PJ ou PF?

Porque estou imaginando algo como um atributo Pessoa:Object na classe Cliente.

Aí creio que o problema seriam os castings constantes quando eu precisasse utilizar as informações exclusivas de Física ou Jurídica.

Acho que o emaranhado está se desfazendo, mas ainda não se desfez. :frowning:

Vou começar a testar a sua sugestão.

Obrigado!
Celso Martins

king_of_gods

Celso de qualquer forma você tem que definir o que uma pessoa é. O computador não vai fazer pra você, tem que ter uma variavel de decisão. Por Exemplo. Se ela quer ser PF, um metodo setClientePF e outro setClientePJ. Dentro desses set’s vc faz o q tem q fazer. Tem que haver uma variavel. Não Adianta. O que você pode fazer é criar uma classe Pessoa e tanto PF E PJ Herdar ela. E criar os metodos na classe cliente tudo com parametro pessoa. Ai na hora de você criar o objeto vc passa… Cliente(…, new PF());

Entendeu?

celso.martins

Obrigado.

Eu sei que a máquina não vai poder decidir isso por mim. O que eu estou buscando é exatamente a melhor solução para fazer essa decisão. A melhor prática. Aprender a melhor forma.

Acho que a sua segunda solução seria a melhor. As classes PF e PJ já herdam de Agente (o equivalente a Pessoa). O que eu não sabia era que podia fazer:

public abstract class Agente{

}

public class PF extends Agente{

}

public class PJ extends Agente{

}

public class Atendimento{
  private Agente cliente;

  public void setCliente(Agente cliente){
    this.cliente = cliente;
  }
}

public class Executa{
  public static void main(String args[]){
    Long codAgente = 1;
    String sql = "SELECT * FROM pf WHERE pfage = " + codAgente;
    Agente cliente;

    if (isEmpty){
      sql = "SELECT * FROM pj WHERE pjage = " + codAgente;
      cliente = new PJ();
    }else{
      cliente = new PF();
    }

    Atendimento a = new Atendimento();
    a.setCliente(cliente);
  }
}

É claro que tudo está bem generalizado, sem PreparedStatement, ResultSets, etc. O que está no método main estaria dentro da classe Cliente, etc, etc.

Mas a idéia é válida?

celso.martins

Bem, funcionou assim. Achei até um pouco bonitinho. Não sei se vai continuar bonitinho assim quando integrar ao meu sistema. Ainda tenho que pensar como vou trabalhar esses castings. Não sei se crio um método “isFisica()”, fazendo o casting em cliente dependendo da resposta. Mas isso me parece uma gambiarra. Se alguém tiver algum conselho, eu agradeceria.

public class Agente {
	
	private String nome;
	
	public Agente() {
		super();
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}
}

public class PF extends Agente {
	private String rg;
	private String cpf;

	public PF() {
		super();
	}
	
	public String getRg() {
		return rg;
	}

	public void setRg(String rg) {
		this.rg = rg;
	}

	public String getCpf() {
		return cpf;
	}

	public void setCpf(String cpf) {
		this.cpf = cpf;
	}
}

public class PJ extends Agente {
	private String cnpj;
	
	public PJ() {
		super();
	}

	public String getCnpj() {
		return cnpj;
	}

	public void setCnpj(String cnpj) {
		this.cnpj = cnpj;
	}
}

public class Atendimento {
	private Agente cliente;

	public Agente getCliente() {
		return cliente;
	}

	public void setCliente(Agente cliente) {
		this.cliente = cliente;
	}

}

public class Executa {

	public static void main(String[] args) {
		boolean pessoa = false;
		Atendimento a = new Atendimento();
		
		if (pessoa) {
			PF cliente = new PF();
			cliente.setNome("Celso");
			cliente.setCpf("123456");
			a.setCliente(cliente);
		}else {
			PJ cliente = new PJ();
			cliente.setNome("Trimbase");
			cliente.setCnpj("987654321");
			a.setCliente(cliente);
		}
		
		if (a.getCliente() instanceof PJ) {
			PJ pj = (PJ) a.getCliente();
			System.out.println(pj.getNome());
			System.out.println(pj.getCnpj());
		}else if (a.getCliente() instanceof PF) {
			PF pf = (PF) a.getCliente();
			System.out.println(pf.getNome());
			System.out.println(pf.getCpf());
		}
	}
}
Criado 7 de agosto de 2007
Ultima resposta 7 de ago. de 2007
Respostas 6
Participantes 2