Baixe o app para aproveitar ainda mais
Prévia do material em texto
Geração de Código Geração de Código • Uma vez definidos os diagramas de colaboração e o diagrama de classes de projeto, a geração de código é uma tarefa passível de automa>zação. • Trata-‐se aqui de gerar o código das classes correspondentes à camada de domínio da aplicação, ou seja, as classes que realizam toda a lógica do sistema a par>r das operações de sistema. • As demais camadas (persistência, interface, etc.) são geradas em outra fase do processo. • Pode-‐se admi>r, porém, que, uma vez gerada a camada de domínio, todas as demais camadas serão derivadas e dependentes desta. Classes class Cliente { }; Atributos class Cliente { private String nome; private Float debito; private Integer idade; } Métodos para alterar e acessar class Cliente { private String nome; private Float debito; private Integer idade; public void setNome(String nome) { this.nome = nome; } public void setDebito(Float debito) { this.debito = debito; } public void setIdade(Integer idade) { this.idade = idade; } public String getNome() { return nome; } public Float getDebito() { return debito; } public Integer getIdade() { return idade; } } Porque não usar atributos públicos? • Deve-‐se observar que para viabilizar o funcionamento do mecanismo de persistência é fundamental que os atributos sejam acessados e modificados unicamente pelas operações de alteração e consulta. • Em hipótese alguma outro método, mesmo métodos da própria classe poderão acessar ou alterar estas variáveis diretamente. • Isso acontece porque quando da implementação do mecanismo de persistência será necessário ter controle sobre qualquer alteração sofrida pelos objetos, para verificar se estão inconsistentes com o banco de dados. • A melhor forma de garan>r isso é sabendo exatamente quais os pontos do código onde os atributos são modificados. Associações • As associações do DCP são transformadas em variáveis de instância, da mesma forma que os atributos, e terão métodos para alteração e consulta. • Os atributos geram sempre variáveis cujos >pos são básicos (alfanuméricos) • As associações geram >pos que são classes de objetos ou estruturas de dados. • Considerando as diferentes mul>plicidades de papel e outras caracterís>cas das associações, haverá algumas dis>nções a fazer quanto aos métodos associados. Associações devem implementar no mínimo • Um método para criar ou redefinir a associação • Um método para remover a associação (exceto para associações para 1) • Um método para obter objetos associados Acesso aos elementos das coleções • Em relação aos métodos que consultam associações com mul>plicidade *, observou-‐se nos diagramas de colaboração que as mensagens de consulta do >po getClienteComNome eram enviadas à coleção em si. • Porém, é indesejável implementar esta consulta desta maneira, pois visto que este método é específico da coleção de clientes, seria necessário especializar a classe genérica com a estrutura de dados que representa a coleção para cada um dos >pos de valor que ela pudesse conter. • Assim, a aplicação teria classes como ColecaoDeClientes, ColecaoDeFitas, ColecaoDeEmprestimos, etc. • Essa abordagem é inconveniente pela proliferação de estruturas pra>camente idên>cas. Como resolver este problema • Uma opção para evitar esse efeito indesejável é implementar o método de consulta na classe que está na origem da associação. • Assim, ao invés de implementar getClienteComNome em uma subclasse de Colecao, implementa-‐se este método na classe Videolocadora visto esta estar na origem da associação. • Desta forma, tanto associações quanto atributos são consultados por métodos da classe prefixados com get. Associação unidirecional para 1 • A associação unidirecional para 1, deve ser armazenada em uma variável de instância na classe de origem da associação e seu >po deve ser a classe de des>no. • Assim, uma associação unidirecional para 1 de ItemDeEmprestimo para Emprestimo corresponderá a uma variável de instância na classe ItemDeEmprestimo declarada com >po Emprestimo. Associação unidirecional para 1 • Como associação é estritamente para 1, então não é possível destruir a associação, e, portanto, o método para destruir a associação não deve ser implementado. • Como a associação para 1 é obrigatória para o objeto na origem, o método criador da classe deve ter como parâmetro o elemento a ser associado para que desde o momento da criação todas as instâncias da classe na origem da associação estejam consistentes. Associação unidirecional para 1 class ItemDeEmprestimo { private Emprestimo emprestimo; public ItemDeEmprestimo(Emprestimo emprestimo) { this.associaEmprestimo(emprestimo ) } public void associaEmprestimo(Emprestimo emprestimo) { this.emprestimo = emprestimo; } public Emprestimo getEmprestimo() { return emprestimo; } } Associação Unidirecional para 0..1 • É possível destruir a associação e, portanto deve ser implementado o método correspondente. • Não é necessário passar um objeto como parâmetro para o método criador, pois a associaçãopara 0..1 não é obrigatória. Associação Unidirecional para 0..1 class Venda { private Pagamento pagamento; public Venda() { } public void associaPagamento(Pagamento pagamento) { this.pagamento = pagamento; } public void desassociaPagamento() { this.pagamento = null; } public Pagamento getPagamento() { return pagamento; } } Associação Unidirecional para * • Corresponde à implementação de um conjunto Associação Unidirecional para * class Cliente { private Set emprestimos = new HashSet(); public Cliente () { } public void adicionaEmprestimo(Emprestimo emprestimo) { this.emprestimos.add(emprestimo); } public void removeEmprestimo(Emprestimo emprestimo) { this.emprestimos.remove(emprestimo); } public Set getEmprestimos () { return Collections.unmodifiableSet(emprestimos); } } Um método alternativo para acesso public Set getEmprestimosNaData(Date data) { private Set empND = new HashSet(); private Emprestimo atual; Iterator inter = emprestimos.iterator(); while (inter.hasNext()) { atual = (Emprestimo) inter.next(); if (atual.data().equals(data)) { empND.add(atual); }; }; return empND; } class Videolocadora { private List reservas = new ArrayList(); public Videolocadora() { } public void adicionaReserva(Reserva reserva, int posicao) { this.reservas.add(posicao,reserva); } public void removeReserva(Reserva reserva) { this.reservas.remove(reserva); } public void removeReservaNaPosicao(int posicao) { this.reservas.remove(posicao); } public List getReservas() { return Collections.unmodifiableList(reservas); } public Reserva getReservaNaPosicao(int posicao) { return (Reserva) reservas.get(posicao); } } Associação Unidirecional <<ordered>> class Videolocadora { private Map cadastro = new HashMap(); public Videolocadora () { } public void adicionaNoCadastro(Cliente cliente) { this.cadastro.put(cliente.getNome(), cliente); } public void removeDoCadastro(Cliente cliente) { this.removeDoCadastroPorNome(cliente.getNome()); } public void removeDoCadastroPorNome(String nome) { this.cadastro.remove(nome); } public Collection getCadastro(){ return cadastro.values(); } public Cliente getCliente(String nome) { return (Cliente) cadastro.get(nome); } } Associação Unidirecional QualiIicada Associação Unidirecional com Classe de Associação class Pessoa { private Map empresas = new HashMap(); public Pessoa() { } public void adicionaEmpresa(Empresa empresa) { this.empresas.put(empresa, new Emprego()); } public void removeEmpresa ( Empresa empresa ) { this.empresas.removeKey(empresa); } public void removeEmprego ( Emprego emprego ) { this.empresas.removeValue(emprego); } public Set getEmpresas () { return empresas.keys() ; } public Set getEmpregos () { return empresas.values() ; } public Emprego getEmpregoNaEmpresa ( Empresa empresa ) { return empresas.at(empresa) } } Associação Unidirecional com Multiplicidade 1 na Origem • a destruição da associação só será possível quando o obje>vo for também destruir o objeto no des>no da associação • No caso de associações de 1 para 0..1 ou de 1 para 1 deve-‐se tomar este mesmo cuidado em relação à operação de criação/ redefinição de associação Associação Bidirecional class Cliente { private Set emprestimos = new HashSet(); public Cliente () {} public void adicionaEmprestimoAux(Emprestimo emprestimo) { emprestimos.add(emprestimo); } public void removeEmprestimoAux(Emprestimo emprestimo) { emprestimos.remove(emprestimo); } public void adicionaEmprestimo(Emprestimo emprestimo) { if (emprestimo.getCliente() != null) { emprestimo.getCliente().removeEmprestimoAux(emprestimo); }; this.adicionaEmprestimoAux(emprestimo); emprestimo.associaClienteAux(this); } public void removeEmprestimo(Emprestimo emprestimo) { this.removeEmprestimoAux(emprestimo); emprestimo.destroi(); } public Set getEmprestimos() { return emprestimos; } } class Emprestimo { private Cliente cliente; public Emprestimo(Cliente cliente) { this.associaCliente(cliente); } public void associaClienteAux(Cliente cliente) { this.cliente = cliente; } public void associaCliente(Cliente cliente) { if (this.cliente != null) { this.cliente.removeEmprestimoAux(this); }; this.associaClienteAux(cliente); cliente.adicionaEmprestimoAux(this); } public Cliente getCliente() { return cliente; } } Método Delegado • Deve-‐se sempre observar o diagrama de colaboração onde ele apareceu. • Toda mensagem com número x, que chega a uma instância da classe A deve ser implementada como a seqüência das mensagens x.1, x.2, ..., x.n, que saem da instância de A e são enviadas a outros objetos. Métodos Delegados e Operações de Sistema class Videolocadora { private Cliente clienteCorrente; private Map acervo = new HashMap(); public void emprestaFita(String codigoF) { private Fita f; f = this.getFita(codigoF); clienteCorrente.emprestaFita(f); } } class Cliente { private Emprestimo emprestimoAberto; public void emprestaFita(Fita f) { if (this.getEmprestimoAberto() == null) { this.criaNovoEmprestimo(); }; this.getEmprestimoAberto().criaNovoItem(f); } } class Cliente { private Emprestimo emprestimoAberto; public void criaNovoEmprestimo() { private Emprestimo e = new Emprestimo(); this.associaEmprestimoAberto(e); e.setData(Sistema.dataDeHoje()); e.setValorTotal(0); } } class Emprestimo { private Set itensDeEmprestimo = new HashSet(); public void criaNovoItem(Fita f) { ItemDeEmprestimo it = new ItemDeEmprestimo(f); this.associaItem(it); this.setValorTotal(this.getValorTotal()+it.getValor()); } } class ItemDeEmprestimo { private EstadoDeItemDeEmprestimo estado; public ItemDeEmprestimo(Fita f) { EmAndamento estado = new EmAndamento(f); this.associaEstado(estado); this.setPrazo(f.getFilme().getTipoDeFilme().getPrazo()); this.setValor(f.getFime().getTipoDeFilme().getValor()); } } Até que ponto desenvolver os diagramas de colaboração? • Desenvolver o diagrama até chegar às mensagens básicas de criação e destruição de instâncias e de associações e de mudança de valor de atributo. • Essas mensagens básicas são normalmente terminais no diagrama de colaboração, sendo as mensagens intermediárias as mensagens delegadas. • Faz-‐se exceção, porém ao caso da operação de criação de instâncias que, conforme foi visto, pode implementar outras mensagens básicas à guisa de inicialização dos atributos e associações do objetosendo criado.
Compartilhar