Diagramas de Classe de Projeto Prof. Tadeu Faria PUC Minas ...

16 downloads 69 Views 768KB Size Report
Diagrama de classe de projeto : especificação de componentes ... ✓ normalmente definidos por questões de ...... Exercício: faça o diagrama de classes para a.
Derivação Projeto Físico em OO

Diagramas de Classe de Projeto Prof. Tadeu Faria PUC Minas

1

Derivação Projeto Físico em OO Bibliografia  GRAIG, Larman. Utilizando UML e Padrões:

uma introdução à análise e ao projeto orientados a objetos. Porto Alegre:Bookman,2005  BEZERRA, Eduardo. Princípios de Análise e Projeto

de Sistemas com UML. Rio de Janeiro: Campus, 2a Edição 2006

2

Classe de Projeto  Ilustram as especificações para classes de software e interfaces em um sistema  Em relação ao Modelo Conceitual, o DCP apresenta: Possível detalhamento dos atributos e operações Adição dos métodos Possível detalhamento das associações navegabilidade (Adição da direção das associações ) Possível adição de relacionamentos de dependências Possível alteração na estrutura das classes (herança) interfaces com suas operações Possível criação de atributos privados ou protegidos Utilização de padrões de projeto (design patterns) 3

Modelo de Domínio X Modelo de Projeto  Modelo conceitual: abstração de conceitos do mundo

real Sale Conceptual Model

POST

Captures 1

1

date isComplete : Boolean time

Concept; abstraction

 Diagrama de classe de projeto : especificação de

componentes de software Design Class Diagram

POST

Sale Captures

endSale() enterItem() makePayment()

1

1

date isComplete : Boolean time makeLineItem()

Software component

4

Modelo de Classe de Projeto  Modelo de classes de projeto:  A criação de classes de projeto deve acontecer em paralelo a criação de diagramas de interação  É construído inicialmente nas iterações da fase de elaboração e refinado nas iterações da fase de construção.  É passado aos programadores para que eles o implementem 5

*** Especificando os atributos  A sintaxe completa da UML para definição de

atributos é: Class Name attribute attribute : type attribute : type = initial value classAttribute /derivedAttribute ... method1() method2(parameter list) : return type abstractMethod() +publicMethod() -privateMethod() #protectedMethod() classMethod() ...

6

Especificando atributos  A sintaxe completa da UML para definição de atributos é:

[/] visibilidade nome : tipo = valor inicial

class Cliente { private String nome; private Float debito; private Integer idade; }

7

Especificando os atributos  Visibilidade permite definir quais atributos de um

objeto são acessíveis por outros objetos  serve para implementar o encapsulamento da estrutura interna da classe  O valor inicial de um atributo é automaticamente definido para o atributo sempre que um objeto da classe é instanciado.

8

Especificando os atributos

Um atributo é derivado quando seu valor pode ser obtido a partir dos valores de outros atributos

É representado por uma barra inclinada normalmente definidos por questões de desempenho

Ex: dataNascimento:Data / idade:int 9

Especificando os atributos

Um atributo pode possuir: Escopo de objeto cada objeto tem um valor para cada atributo definido em sua classe Escopo de classe atributos que armazenam um valor comum a todos os objetos da classe, denominado atributo estático pode ser utilizado para implementar regras de negócio. Ex: Em um curso podem estar matriculados até 30 alunos representado com um sublinhado

10

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 garantir isso é sabendo exatamente

quais os pontos do código onde os atributos são modificados.

11

Definição dos atributos: geração de código

class Cliente { private String nome; private Float debito; private Integer idade; }

12

*** Especificando Operações A sintaxe da UML para a assinatura é semelhante a de uma linguagem de programação visibilidade nome(parâmetros): tipo-retorno {propriedades} Onde, para cada parâmetro: direção nome-parâmetro: tipo-parâmetro

13

Especificando operações  Operação: um processamento realizado por

(um objeto de) uma classe. – Em termos de implementação: é uma rotina associada

a uma classe.

 Na construção do modelo de interações,

operações identificadas na análise são validadas e várias outras operações são identificadas. – Essas operações devem ser adicionadas ao diagrama

de classes e documentadas através da definição de sua assinatura. 14

Especificando operações assinaturas • Durante o projeto é determinada a assinatura de cada operação • argumentos da operação • tipo de retorno da operação

análise curso +adicionaaluno(newaluno)

projeto curso +adicionaaluno(newaluno:aluno*):void

15

Especificando operações

 Os parâmetros de uma operação correspondem a informações que esta recebe quando é executada

cada parâmetro da lista tem a seguinte sintaxe: direção nome-parâmetro: tipo-parâmetro

Direção Significado in

Parâmetro de entrada

out

Parâmetro de saída.

inout

Parâmetro de entrada e de saída. 16

Especificando operações • Durante a análise são criadas operações para implementar o comportamento expresso nos casos de uso • durante o projeto: • são adicionadas a essas classes os detalhes de implementação • são acrescentadas operações adicionais para tornar as classes mais completas

17

Especificando operações

Acrescentando atributos, operações e informações de tipos às classes

18

Operações de criação e destruição  Operações utilizadas freqüentemente nas

interações entre objetos.  Os parâmetros de uma operação de criação

servem para iniciar atributos do objeto. – Regra prática: se o valor de um atributo é

essencial para o significado do objeto, é mais adequado iniciar o seu valor logo na criação do objeto.

 Operações de destruição servem para liberar

memória alocada dinamicamente. 19

Operações de criação e destruição  Operações de criação são identificadas na

construção dos diagramas de interação.  Operações de criação também são

utilizadas para definir o estado inicial de um objeto que passa por um conjunto de estados relevantes durante a sua existência.

20

Operações de criação e destruição  Métodos create  Métodos de instanciação (construtores) específicos para cada

linguagem de programação  Normalmente omitidos no diagrama de classe  Métodos de acesso  get e set de atributos  Omitidos no diagrama para reduzir ruído (2N métodos

desinteressantes para cada N atributos)  Métodos de coleção (multiobjects)  Parte da definição da coleção (classes de biblioteca do tipo

container: Vetor, Hashtable, etc.)  Omitidos no diagrama para reduzir ruído

21

Operações para alterar e acessar:geração código 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; } } 22

Membros estáticos  Membros estáticos são representados no

diagrama de classes por declarações sublinhadas. – Atributos estáticos (variáveis de classe) são

aqueles cujos valores valem para a classe de objetos como um todo. – Diferentemente de atributos não-estáticos (ou variáveis de instância), cujos valores são particulares a cada objeto.

– Métodos estáticos são os que não precisam da

existência de uma instância da classe a qual pertencem para serem executados. – Forma de chamada: NomeClasse.Método(argumentos) 23

*** Relacionamentos classes  Na UML, há três tipos de relacionamentos entre

objetos: – Associações – Dependências – Generalizações

 No modelo de classes de domínio, os

relacionamentos entre objetos foram identificados como associações. 24

*** Associações  Associação : São relacionamentos estruturais entre

instâncias e especificam que objetos de uma classe estão ligados a objetos de outras classes. Podemos ter associação uniária , binária , etc.

 A associação pode existir entre classes ou entre objetos.

Uma associação entre a classe Professor e a classe disciplina (um professor ministra uma disciplina) significa que uma instância de Professor (um professor específico) vai ter uma associação com uma instância de Disciplina. Esta relação significa que as instâncias das classes são conectadas, seja fisicamente ou conceitualmente.[Nicolas Anquetil] 25

*** Associações  Sempre que um atributo de uma classe não é de

tipo primitivo, temos uma associação desta classe com alguma outra.  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 tipos são básicos (alfanuméricos)  As associações geram tipos que são classes de objetos ou estruturas de dados.  Considerando as diferentes multiplicidades de papel e outras características das associações, haverá algumas distinções a fazer quanto aos métodos associados.

26

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

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; } }

27

Associações:exemplo 1  Suponhamos uma classe

Cliente com dois atributos apenas, código e dataDeNascimento. O código é um número inteiro que identifica o cliente, portanto, um tipo primitivo (int), mas a data de nascimento é do tipo Data

Cliente cod : Integer dataNasc : Data

Data

28

Associações:exemplo 1 Classe data public class Data { private int dia; private int mes; private int ano; } Classe cliente public class Cliente { private int codigo; private Data dataDeNascimento; public Cliente(int umCodigo, int umDia, int umMes, int umAno) { codigo = umCodigo; dataDeNascimento = new Data(umDia, umMes, umAno); } .... }

Uma outra alternativa é criar o objeto cliente sem uma data de nascimento e inserila mais tarde. Neste caso, precisamos um outro construtor (sobrecarregado) com um só parâmetro para o codigo: public Cliente(String umCodigo) { codigo = umCodigo; dataDeNascimento = null; 29

Associações:exemplo 2 public class Cliente {

Suponha uma classe cliente relacionada com uma classe dependente

Cliente nome : String apelido : String endereco : String0..*

//Declaração dos atribultos private String nome; private String endereco; private String apelido; protected Dependente dependente; //Construtor padrão public Cliente(){} //Construtor com atributos public Cliente(String nome, String endereco,String apelido ){ this.nome = nome; this.endereco = endereco; this.apelido = apelido; } //Get public String getApelido() { return apelido; } public String getEndereco() { return endereco; } public String getNome() { return nome; } public Dependente getDependente() { return dependente; } //Set public void setApelido(String apelido) { this.apelido = apelido; } public void setEndereco(String endereco) { this.endereco = endereco; } public void setNome(String nome) { this.nome = nome; } public void setDependente(Dependente dependente) { this.dependente = dependente; }

Dependente 1

nome : String numero : Integer

30 }

Associações:exemplo 2 

public class Dependente { private String nomeDep; private double numero; //Criação de uma lista de clientes dentro de dependentes //neste caso o dependete possui um relacionamento 1 para n //ou seja o cliente pode ser de vários dependentes protected List listaCliente = new ArrayList(); //Construtor padrão public Dependente() {} //Construtor com argumentos public Dependente(String nomeDep, double numero){ this.nomeDep = nomeDep; this.numero = numero; } //Get public String getNomeDep() { return nomeDep; } public double getNumero() { return numero; } public List getListaCliente() { return listaCliente; } //Set public void setNomeDep(String nomeDep) { this.nomeDep = nomeDep; } public void setNumero(double numero) { this.numero = numero; } public void setListaCliente(List listaCliente) { this.listaCliente = listaCliente; } }

31

Associações:exemplo 2 public class TesteClasses { public static void main(String[] args) { //utilizado o construtor com argumentos onde o double é representado por D Dependente dependente1 = new Dependente("João",1D); Dependente dependente2 = new Dependente("Maria", 2D); Cliente cliente = new Cliente("Cliente pai","rua que sobe e desce","cli"); Cliente cliente2 = new Cliente("Cliente mãe","rua Belo Horizonte","cli 2"); cliente.setDependente(dependente1); cliente2.setDependente(dependente2); cliente.imprimeDados("dependente 2 --> ", cliente); //Parte 2 removendo a associação do dependente com cliente 2 cliente2.setDependente(null); //Parte 3 criando a associação sem dependente Cliente clienteNull = new Cliente("Cliente pai","rua que sobe e desce","cli"); Cliente clienteNull2 = new Cliente("Cliente mãe","rua Belo Horizonte","cli 2"); clienteNull.setDependente(null); clienteNull2.setDependente(null); //parte 4 Cliente clienteNumero1 = new Cliente("Cliente 1","endereco 1", "cle 1"); Cliente clienteNumero2 = new Cliente("Cliente 2","endereco 2", "cle 2"); Cliente clienteNumero3 = new Cliente("Cliente 3","endereco 3", "cle 3"); Cliente clienteNumero4 = new Cliente("Cliente 4","endereco 4", "cle 4"); //Associação do dependente para n clientes Dependente dependenteDeTodos = new Dependente("dependente de todos", 10D); dependenteDeTodos.getListaCliente().add(clienteNumero1); dependenteDeTodos.getListaCliente().add(clienteNumero2); dependenteDeTodos.getListaCliente().add(clienteNumero3); dependenteDeTodos.getListaCliente().add(clienteNumero4); //iteração na lista de clientes dentro do dependente usado //a nomenclatura do For moderno consiste em primeiro a Classe pelo qual será iterado //o objeto desta classe sendo que o garbaje collector retira do heap assim que termina o for //e a coleção para iteração for (Cliente clienteIteracao : dependenteDeTodos.getListaCliente()) { System.out.println("o cliente pertence ao cliente --> " + clienteIteracao.getNome()); } }}

32

Navegabilidade de associações  Navegabilidade é a propriedade do papel que indica

que é possível navegar unidirecionalmente por meio da associação de objetos da classe de origem para a classe destino  A navegabilidade implica geralmente em visibilidade

por atributo (associação)  A maioria das associações no diagrama de classe de

projeto deve estar adornada com setas de navegabilidade

33

Navegabilidade de associações  Associações, agregações e composições

podem ser bidirecionais e unidirecionais.  Uma associação bidirecional indica que há um

conhecimento mútuo entre os objetos associados.  Na UML, associações são, por omissão,

navegáveis em ambos os sentidos.  Uma associação unidirecional é representada

adicionando-se um sentido à seta da associação.

34

Navegabilidade de associações  No modelo de classes de projeto, a

navegabilidade de todas as associações deve ser definida. – Algumas associações permanecem bidirecionais. – Se não houver essa necessidade, recomenda-se

transformar a associação em unidirecional.

 A escolha do sentido da navegabilidade pode

ser feita através dos diagramas de interação. – Mensagens influenciam na existência ou não de

navegabilidade em um sentido.

35

Navegabilidade de associações  Na análise, as associações são bi-direcionais  No projeto, uma associação pode ser uni-direcional; uma seta

é adicionada à associação para mostrar que a navegação é em uma direção C lie n te

P e d id o 0 ..* O cliente pode ‘conversar’ com pedido O pedido não pode ‘conversar’ com o cliente

 A necessidade de navegação é revelada por casos de uso e cenários.  dada uma instância de A, precisamos encontrar todas as instâncias

associadas da classe B ou vice-versa?

36

Navegabilidade de associações  Situações comuns que indicam uma

necessidade de definir uma associação com um adorno de navegabilidade de A para B – A envia uma mensagem para B – A cria uma instância B – A precisa manter uma conexão com B

37

Navegabilidade de associações : Loja

:

cp : CatalogoProduto

: EspecificaçãoProduto

ep : EspecificaçãoProduto

: Registro

criar( ) criar( ) criar( ) carregarEspProd( ) criar(id : , preco : , descricao : )

criar(cp : )

Cat alogoP rodut o Loja c riar() 1



Observando o diagrama é discernível que Loja tenha uma associação permanente com instâncias de registro e de CatalogoProduto que criou e que CatalogoProduto também tenha uma conexão permanente com Especificaçãoproduto

us a 1

1

c riar() c arregarE s pP rod() 1

ab riga

po s s ui

1 Regis tro

1..* E s pec ific aç ão P rodut o

c riar()

c riar() c riar()

38

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 tipo deve ser a classe de destino.  Assim, uma associação unidirecional para 1 de ItemDeEmprestimo para Emprestimo corresponderá a uma variável de instância na classe ItemDeEmprestimo declarada com tipo Emprestimo.

39

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.

40

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; } }

41

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ção para 0..1 não é obrigatória.

42

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; } }

43

Associação Unidirecional para *  Corresponde à implementação de um

conjunto

44

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); } }

45

Tratando classes de associação Durante o projeto, classes de associação

evoluem para:

– Tranformação de uma classe de associação em uma

classe interposta entre as classes originais; – Estabelecimento de associações com mutiplicidade apropriada entre a classe de associação e as outras duas classes – Projeto de novas associações. A navegação pode ser bi-direcional ou uni-direcional. Curso

Aluno 1..*

1..*

Boletim

Curso

Boletim 1

*

Aluno *

1

46

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) }

47

Associação Unidirecional com Multiplicidade 1 na Origem  a destruição da associação só será possível

quando o objetivo for também destruir o objeto no destino 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

48

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; } }

49

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; } }

50

agregações Agregação Regular - tipo de associação ( é parte de

, todo/parte) onde o objeto parte é um atributo do todo ; onde os objetos partes somente são criados se o todo ao qual estão agregados seja criado. Pedidos é composto por itens de pedidos. Composição - Relacionamento entre um elemento ( o todo) e outros elementos (as partes) onde as parte só podem pertencer ao todo e são criadas e destruídas com ele.

51

Navegabilidade de agregações Navegabilidade em Agregações:  Uma agregação também pode ser uni-direcional

durante o projeto.  Os relacionamentos podem ser de dois tipos: Por referência (agregation) – implica que os tempos de vida dos objetos relacionados podem ser independentes;  Por valor (composition) – implica que os objetos são criados e destruídos em consequencia da criação ou destruição de um outro objeto.ItemPedido Pedido 0..* 52

Relacionamentos de dependência  O relacionamento de dependência indica que uma classe depende (ou

tem conhecimento) dos serviços fornecidos por uma outra classe.  São relacionamentos de utilização no qual uma mudança na

especificação de um elemento pode alterar a especificação do elemento dependente. A dependência entre classes indica que os objetos de uma classe usam serviços dos objetos de outra classe. – características de implementação.  É útil para representar as visibilidades (slides a seguir) não mostradas

no diagrama de classes, isto é: – Dependência por variável global. – Dependência por variável local. – Dependência por parâmetro.

53

relacionamentos de dependência  Representado através de uma linha direcionada e

tracejada ligando as classes envolvidas.  A direção é da classe dependente (cliente) para a classe da qual ela depende (fornecedora).  Estereótipos: global, local, parameter. Um relacionamento de dependência indica que: Operações da classe cliente criam objetos da classe fornecedor; Operações da classe cliente possuem métodos cuja classe de retorno ou seus argumentos são instâncias da (ou se referenciam à) classe fornecedor 54

relacionamentos de dependência Exemplo

55

Visibilidade entre Objetos  Capacidade de um objeto “ver” ou ter uma referência

para outro objeto – Necessária para comunicação (envio de mensagens) entre

objetos

 Relacionada a questão de escopo: uma instância está

dentro do escopo do outro  Para um objeto A enviar uma mensagem para um objeto B, B deve ser visível para A  Estabelece um relacionamento de dependência que

indica que uma classe depende (ou tem conhecimento) dos serviços fornecidos por uma outra classe. 56

Visibilidade entre Objetos  Quatro maneiras de B ser visível para A: – Visibilidade de atributo (associação) — B é um atributo de A (as classes de dois objetos estão associadas) – Visibilidade de parâmetro — B é um parâmetro de um método de A (quando um objeto recebe outro como parâmetro em um de seus métodos) – Visibilidade declarada localmente — B é declarado como objeto local de um método de A (quando um objeto recebe outro como retorno de um método – Visibilidade global — B é de algum modo visível globalmente 57

Visibilidade de Atributo (associação)  Existe de A para B

quando B é um atributo de A – Permanente — persiste

enquanto A e B existirem

58

Visibilidade por Parâmetro  Existe de A para B quando B é passado como um

parâmetro para um método de A – Temporária — persiste apenas dentro do escopo do método

de A (permanente se B é atribuído a um atributo de A)

59

Visibilidade por Parâmetro Msg( c) :Emprestimo

> 60

Visibilidade Local  Existe de A para B quando B é declarado como um objeto local dentro de um método de A – Temporária — persiste apenas dentro do escopo do método de A (permanente se B é atribuído a um atributo de A) – Duas maneiras comuns de alcançar: – 1. Criar nova instância e atribuir para variável local – 2. Atribuir objeto de retorno de um método para variável local

61

Visibilidade local f:=msg( c) :EstadoDeItemDeEmprestimo

ItemDeEmprestimo

>

62

Visibilidade Global  Existe de A para B quando B é global para A – Permanente — persiste enquanto A e B existirem  Forma menos comum de visibilidade em

sistemas desenvolvidos utilizando OO

– Maneira mais comum (mas não recomendada) de

atingir é atribuir nova instância a uma variável global

 Alternativa recomenda: – Padrão Singleton (GoF)

63

Notação de Visibilidade na UML  Uso opcional de “estereótipos” específicos

64

Detalhes de visibilidade de membros de classes em UML Significado

Símbolo

Visibilidade

Pública

+

Qualquer objeto externo pode obter acesso ao membro, desde que tenha uma referência para aclasse em que o membro está definido

Protegida

#

Visível às subclasses

Privativa

_

Invisível externamente a classe em que está definido

65

Transformação de associações em dependências  Na passagem para o modelo de projeto cada

associação deve ser considerada para identificar se ela pode ser transformada em dependências.  Razão: aumentar o encapsulamento das

classes – Dependência por atributo torna as classes

envolvidas mais dependentes uma da outra. – Quanto menos dependências estruturais houver

no modelo de classes, maior é o encapsulamento das classes constituintes.

66

Transformação de associações em dependências  Associações que ligam classes de entidade permanecem como

associações.  Associações entre controladores e classes de entidade:

bastante suscetíveis à transformação.  Associações entre classes de fronteira e controladores:  classe de fronteira para esse ator: essa classe pode manter

um relacionamento estrutural com o controlador (composição).  classes de fronteira para equipamentos ou outros sistemas:

interfaces, dependência não estrutural.

67

*** Relacionamento de Herança durante o projeto, as hierarquias de heranças são

refinadas para: aumentar o reuso incorporar classes de implementação incorporar bibliotecas de classes disponíveis

diagramas de análise são revisados para identificar

similaridades em atributo operações associações

 novas superclasses são definidas para conter elementos

comuns 68

Relacionamento de Herança  Na modelagem de classes de projeto, há

diversos aspectos relacionados ao de relacionamento de herança. – Tipos de herança – Classes abstratas – Operações abstratas – Operações polimórficas – Interfaces – Acoplamentos concreto e abstrato – Reuso através de delegação e através de

generalização – Classificação dinâmica

69

Tratamento hierarquias de herança 

Exercício: faça o diagrama de classes para a seguinte descrição: –



– –



Em um sistema de ofertas de emprego na internet uma empresa pode ofertar diversas vagas. Uma vaga esta relacionada a somente uma empresa. Um candidato, previamente cadastrado, pode fazer inscrição em uma vaga. Um candidato pode fazer inscrição em mais de uma vaga. O candidato selecionado recebe uma matricula. No processo de avaliação de contratação, um funcionário recebe diversas ocorrências empresa e faz a inscrição.

Refaça o diagrama considerando possíveis reestruturações das classes para otimizar o modelo

70

Tipos de herança  Com relação à quantidade de superclasses

que certa classe pode ter. – herança múltipla – herança simples

 Com relação à forma de reutilização

envolvida. – Na herança de implementação, uma classe reusa

alguma implementação de um “ancestral”. – Na herança de interface, uma classe reusa a interface (conjunto das assinaturas de operações) de um “ancestral” e se compromete a implementar essa interface.

71

Herança ⇒ Hierarquia de Classes Em Java, Object é a superclasse de todas as classes.

Object Animal peso

peso é uma variável de instância que está presente em todos os objetos criadas para as classes Animal, Mamífero, Ave e Réptil.

locomover ()

Mamífero Mamífer peso o comer()

Ave Ave peso andar() locomover( voar()

Réptil Réptil peso andar() locomover( nadar()

voar()

nadar()

)

)

72

Herança ⇒ Hierarquia de Classes Object Animal peso

peso é uma variável de instância que está presente em todos os objetos criadas para as classes Animal, Mamífero, Ave e Réptil.

locomover( )

Mamífero comer()

Ave pardal = new Ave(); pardal.peso = 700;

Ave

Réptil

locomover( )

locomover( )

voar()

nadar()

Mamifero boi = new Mamifero() boi.peso = 30000; boi.locomover(); // boi.voar(); não existe!

73

Herança

Busca Dinâmica de Métodos Mamifero boi = new Mamifero() boi.peso = 30000; boi.andar(); boi.locomover();

Object Animal peso

boi this

locomover( )

Mamífero comer()

peso = 30000 0

Ave

Réptil

locomover( )

locomover( )

voar()

nadar()

74

Herança  Estender uma classe causa dois efeitos: – criação de um subtipo. – todas as declarações da classe estendida (superclasse)

são incluídas na subclasse, a menos que elas tenham sido sobrepostas.

75

Definindo a Superclasse  Forma geral: – class extends SuperClass

– é permitido apenas uma superclasse.  não há herança múltipla em Java. – cada classe apresenta exatamente uma superclasse.  exceção: java.lang.Object – caso não exista a cláusula extends, então, assumese que a superclasse é Object.

76

Exemplo de Herança class Animal { int peso; void locomover() { /* movimentação do animal */ } } class Mamifero extends Animal { void comer() }

Sobreposição de método!

class Ave extends Animal { void locomover() { } void voar() { } }

77

A Classe Object  A classe java.lang.Object forma a raiz da

hierarquia de classes. – Direta ou indiretamente, toda classe é uma subclasse de

Object.

 Object define alguns métodos úteis, incluindo: – String toString(); – boolean equals(Object outro).

78

Classes abstratas  Usualmente, a existência de uma classe se justifica

pelo fato de haver a possibilidade de gerar instâncias a partir da mesma. – Essas classes são chamadas de classes concretas.  No entanto, podem existir classes que não geram instâncias “diretamente”. – Essas classes são chamadas de classes abstratas.  Classes abstratas são usadas para organizar hierarquias gen/spec. – Propriedades comuns a diversas classes podem ser organizadas e definidas em uma classe abstrata a partir da qual as primeiras herdam.  Também propiciam a implementação do princípio do polimorfismo. 79

Classes abstratas (cont)  Na UML, uma classe abstrata pode ser representada de duas maneiras alternativas:  Com o seu nome em itálico.  Qualificando-a com a propriedade {abstract}

 Classe abstratas:  Não podem ser instanciadas  Não pode utilizar operador new  Palavra chave: abstract.

public abstract class ContaBancaria { public void sono() { } } 80

Operações abstratas  Uma classe abstrata possui ao menos uma operação abstrata, que corresponde à especificação de um serviço que a classe deve fornecer (sem método).  Uma classe qualquer pode possuir tanto operações abstratas, quanto operações concretas (ou seja, operações que possuem implementação).  Entretanto, uma classe que possui pelo menos uma operação abstrata é, por definição abstrata, abstrata.

 Uma operação abstrata definida com visibilidade pública em uma classe também é herdada por suas subclasses.  Quando uma subclasse herda uma operação abstrata e não fornece uma implementação para a mesma, esta classe também é abstrata. 81

Operações abstratas (cont)  Na UML, a assinatura de uma operação abstrata é definida em itálico.

82

Operações Abstratas  Não possui corpo.  Apresenta apenas a definição seguida de “;”  Apresenta o modificador abstract. public abstract class Animal { public int peso; public abstract void locomover(); }

83

Exemplo de Abstração public abstract class FiguraGeometrica { public abstract double area(); public abstract double perimetro(); } public class Retangulo extends FiguraGeometrica { protected double w, h; public Retangulo() { this(0.0,0.0); } public Retangulo(double l, double a) { w = l; h = a; } public double area() { return w*h; } public double perimetro() { return 2*w*h; } }

84

Polimorfismo Conceito complementar a herança que permite enviar a mesma mensagem a objetos distintos, onde cada objeto responde da maneira mais apropriada para a sua classe.

85

Operações polimórficas  Uma subclasse herda todas as propriedades de sua

superclasse que tenham visibilidade pública ou protegida.  Entretanto, pode ser que o comportamento de alguma operação herdada seja diferente para a subclasse.  Nesse caso, a subclasse deve redefinir o comportamento da operação. – A assinatura da operação é reutilizada. – Mas, a implementação da operação (ou seja, seu método) é diferente.  Operações polimórficas são aquelas que possuem mais de uma implementação. 86

Operações polimórficas (cont)  Operações polimórficas possuem sua assinatura definida em

diversos níveis de uma hierarquia gen/spec. – A assinatura é repetida na(s) subclasse(s) para enfatizar a redefinição de implementação. – O objetivo de manter a assinatura é garantir que as subclasses tenham uma interface em comum.  Operações polimórficas facilitam a implementação. – Se duas ou mais subclasses implementam uma operação polimórfica, a mensagem para ativar essa operação é a mesma para todas essas classes. – No envio da mensagem, o remetente não precisa saber qual a verdadeira classe de cada objeto, pois eles aceitam a mesma mensagem. – A diferença é que os métodos da operação são diferentes em cada subclasse.

87

Operações polimórficas (cont)  A operação obterPagamento é polimórfica.

88

Operações polimórficas (cont)  Operações polimórficas também podem

existir em classes abstratas.

89

Operações polimórficas (cont)  Operações polimórficas implementam o

princípio do polimorfismo, no qual dois ou mais objetos respondem a mesma mensagem de formas diferentes. ContaCorrente cc; ContaPoupanca cp; ... List contasBancarias; ... contasBancarias.add(cc); contasBancarias.add(cp); ... for(ContaBancaria conta : contasBancarias) { conta.aplicarJuros(); } ... 90

Operações polimórficas (cont) Animal

 Exemplo

sono() comida()

gato

cachorro

tigre

Lobo

Leao

Animal[] animais[] = new Animal[5];Os métodos são executados de acordo com o objeto animais[0] = new Cachorro(); animais[1] = new gato(); animais[2] = new Lobo(); animais[3] = new tigre(); animais[4] = new leao(); for (int i = 0; i < animais.length(); i++) { animais[i].comida(); animais[i].sono(); }

91

Polimorfismo  Existem três tipos de polimorfismos em Java: – Sobrecarga – Sobreposição (entre superclasse e subclasse) – Generalização (subtipo & coerção)

92

Polimorfismo  SOBRECARGA – Métodos (procedimentos) com o mesmo nome, mas com

argumentos diferentes. – Identificados por:

– nome do método; – tipo de dados dos parâmetros.

93

Polimorfismo  SOBREPOSIÇÃO – Métodos (procedimentos) com o mesmo nome, mas com

funcionalidades diferentes.

– Permite que uma subclasse herde um método da superclasse

e implemente-o de forma diferente.

– Identificados por:

– classe do objeto. – conteúdo do objeto.

94

Sobrecarga x Sobreposição class Ave extends Animal { private int altura, velocidade; Ave() { altura = 0; velocidade = 0; } void locomover() { velocidade = 2; } void locomover(int vel); { velocidade = vel; } void parar() { andar(0); } void voar() { altura = 10; velocidade = 30; } }

{

Ave.locomover() sobrepõe o método de Animal.locomover( ). locomover() também é sobrecarregado na classe Ave.

95

Sobreposição de Variáveis  Ao sobrepor variáveis, podemos referenciar a

variável da superclasse através da palavra super.

class A { int a; A() { a = 1; } }

class B extends A { int a, b; B() { super(); a = super.a; b = 2; } } 96

Sobreposição de Métodos  Um

método da superclasse também pode ser invocado usando a palavra super.

class A { int i = 1; int f() { return i;} }

class B extends A { int i; //sobrepõe atributo int f() //sobrepõe { f() de A i = super.i + 1; //A.i return super.f() + //A.f() } }

o i de A o método

i;

97

Interfaces  Uma interface entre dois objetos compreende

um conjunto de assinaturas de operações correspondentes aos serviços dos quais a classe do objeto cliente faz uso.  Uma interface pode ser interpretada como um contrato de comportamento entre um objeto cliente e eventuais objetos fornecedores de um determinado serviço. – Contanto que um objeto fornecedor forneça

implementação para a interface que o objeto cliente espera, este último não precisa conhecer a verdadeira classe do primeiro.

98

Interfaces (cont.)  Interfaces são utilizadas com os seguintes objetivos: 1. Capturar semelhanças entre classes não relacionadas sem forçar relacionamentos entre elas. 2. Declarar operações que uma ou mais classes devem implementar. 3. Revelar as operações de um objeto, sem revelar a sua classe. 4. Facilitar o desacoplamento entre elementos de um sistema.

 Nas LPOO modernas (Java, C#, etc.), interfaces são

definidas de forma semelhante a classes. – Uma diferença é que todas as declarações em uma interface

têm visibilidade pública. – Adicionalmente, uma interface não possui atributos, somente declarações de assinaturas de operações e (raramente) constantes. 99

Interfaces (cont.)  Em JAVA, classes só podem ter um ancestral direto, ou seja, só



 



podem ser derivadas de uma única classe (embora esta possa ser derivada de outra e assim por diante). Existem situações, porém, onde pode ser necessário que uma classe herde características de mais de uma “superclasse” simultaneamente. Como a herança múltipla não é permitida em JAVA, a linguagem oferece a o conceito de interface como opção. Uma interface define um conjunto de métodos que uma classe deve implementar mas não define como esses métodos devem ser implementados. Define, na verdade, uma lista de métodos que toda a classe que segue determinada interface deve prover.

10 0

Interfaces (cont)  Notações para representar interfaces na

UML:

– A primeira notação é a mesma para classes. São

exibidas as operações que a interface especifica. Deve ser usado o estereótipo . – A segunda notação usa um segmento de reta com um pequeno círculo em um dos extremos e ligado ao classificador. – Classes clientes são conectadas à interface através de um relacionamento de notação similar à do relacionamento de dependência.

10 1

Interfaces (cont) Exemplo: ICMS pode ser diferenciado dependendo do tipo de produto. Para evitar que um programa chame cada classe específica para calcular o ICMS, pode-se criar uma interface que vai ser acionada pelo programa. A implementação dela está nas classes específicas de cada produto. ; public interface ICMS { static final double aliquota = 0.9; public abstract double meuICMS(); }

usa

Classe cliente

IMPLEMENTA class Carro implements ICMS { String fabricante, modelo; int ano, vel_max, peso; float preco; int num_rodas = 4; int num_portas; public double meuICMS() { return 0.17 * preco; } }

class Consultoria implements ICMS { double valor; public double meuICMS() { return 0.1 * valor; }

10 2

Diferenças entre Classes abstratas e Interfaces  Uma interface é como um conjunto de regras

(contrato) definidas e que devem ser rigorosamente seguidas (implementadas). – Interface é quando você apenas quer definir um

"contrato" que as classes devem realizar (implementar) – uma interface é uma maneira de descrever o que a classe vai fazer, ao invés de como ela faria

10 3

Diferenças entre Classes abstratas e Interfaces  A herança possibilita o reaproveitamento de código,

onde cada subclasse herda as características da super classe.  Uma classe abstrata pode conter métodos implementados e métodos não-implementados, ou seja, abstratos. – Em uma interface, todos os métodos são abstratos – Uma interface é como uma classe 100% abstrata.

 com uma classe abstrata, pode-se criar os métodos

com a lógica em comum para todos os casos, e deixar os métodos dependentes de implementação que serão abstract - serem feitos pelas subclasses. – Toda classe que possui métodos abstratos é

automaticamente abstrata e deve ser declarada como tal

10 4

Diferenças entre Classes abstratas e Interfaces  Classes abstratas: –

Podem possuir atributos não estáticos



Podem implementar alguns métodos

 Uma classe só pode herdar de apenas outra classe. Logo, não podemos

ter uma mesma classe que herde de duas classes abstratas. –

Não pode possuir atributos não estáticos



Não pode implementar nenhum método

 Uma classe pode implementar mais de uma interface. Ou seja,

possibilita boa parte dos recursos de herança múltipla sem problemas de conflitos de nomes dos atributos. public class MyClass extends SuperClass1 implements Interface1, Interface2, Interface3

10 5

Diferenças entre Classes abstratas e Interfaces  uma classe abstrata é uma classe "incompleta", onde

define-se o esqueleto base para as classes filhas e, ao contrario de uma Interface, pode-se ter também métodos reais, que façam algo. –

Util para casos onde quer prover as funcionalidades básicas e deixar a especializacão/criação de outros métodos para as classes mais especificas..

 Uma interface é utilizada quando não existe a

necessidade das classes derivadas herdarem métodos já implementados.  Sugestão: Use classes abstratas somente quando realmente não puder usar interfaces.

10 6

Diferenças entre Classes abstratas e Interfaces  Diferentemente das classes, uma interface

pode herdar de mais de uma interface  Para que usar interfaces?

– Uma interface é utilizada quando não existe a

necessidade das classes derivadas herdarem métodos já implementados – Para deixar o código mais flexível, e possibilitar a mudança de implementação sem maiores traumas. – Elas também trazem vantagens em não acoplar as classes. Uma vez que herança através de classes traz muito acoplamento, muitos autores clássicos dizem que em muitos casos herança quebra o encapsulamento. 10 7

Especificação de classes de fronteira  Não devemos atribuir a essas classes

responsabilidades relativas à lógica do negócio. – Classes de fronteira devem apenas servir como um ponto de

captação de informações, ou de apresentação de informações que o sistema processou. – A única inteligência que essas classes devem ter é a que permite a elas realizarem a comunicação com o ambiente do sistema.

 Há diversas razões para isso: – Em primeiro lugar, se o sistema tiver que ser implantado em

outro ambiente, as modificações resultantes sobre seu funcionamento propriamente dito seriam mínimas. – Além disso, o sistema pode dar suporte a diversas formas de interação com seu ambiente (e.g., uma interface gráfica e uma interface de texto). – Finalmente, essa separação resulta em uma melhor coesão.

10 8

Especificação de classes de fronteira  Durante a análise, considera-se que há uma única classe de

fronteira para cada ator. No projeto, algumas dessas classes podem resultar em várias outras.  Interface com seres humanos: projeto da interface gráfica produz o detalhamento das classes.  Outros sistemas ou equipamentos: devemos definir uma ou mais classes para encapsular o protocolo de comunicação. – É usual a definição de um subsistema para representar a comunicação com outros sistemas de software ou com equipamentos. – É comum nesse caso o uso do padrão Façade (mais adiante)  O projeto de objetos de fronteira é altamente dependente da natureza do ambiente…

10 9

Especificação de classes de fronteira  Clientes WEB clássicos – Classes de fronteira são representadas por páginas HTML que,

muitas vezes, representam sites dinâmicos.  Clientes móveis – Classes de fronteira implementam algum protocolo específico com o ambiente. – Um exemplo é a WML (Wireless Markup Language).  Clientes stand-alone – Nesse caso, é recomendável que os desenvolvedores pesquisem os recursos fornecidos pelo ambiente de programação sendo utilizado. – Um exemplo disso é o Swing/JFC da linguagem Java.  Serviços WEB (WEB services) – Um serviço WEB é um uma forma de permitir que uma aplicação forneça seus serviços (funcionalidades) através da Internet.

11 0

Especificação de classes de entidade  A maioria das classes de entidade normalmente permanece na

passagem da análise ao projeto. – Na verdade, classes de entidade são normalmente as primeiras classes a serem identificadas, na análise de domínio.  Durante o projeto, um aspecto importante a considerar sobre classes de entidade é identificar quais delas geram objetos que devem ser persistentes. – Para essas classes, o seu mapeamento para algum mecanismo de armazenamento persistente deve ser definido .  Um aspecto importante é a forma de representar associações, agregações e composições entre objetos de entidade. – Essa representação é função da navegabilidade e da multiplidade definidas para a associação, conforme visto mais adiante. 11 1

Especificação de classes de entidade  Outro aspecto relevante para classes de entidade é modo como

podemos identificar cada um de seus objetos unicamente. – Isso porque, principalmente em sistemas de informação, objetos de entidade devem ser armazenados de modo persistente. – Por exemplo, um objeto da classe Aluno é unicamente identificado pelo valor de sua matrícula (um atributo do domínio).  A manipulação dos diversos atributos identificadores possíveis em uma classes pode ser bastante trabalhosa.  Para evitar isso, um identificador de implementação é criado, que não tem correspondente com atributo algum do domínio. – Possibilidade de manipular identificadores de maneira uniforme e eficiente. – Maior facilidade quando objetos devem ser mapeados para um SGBDR 11 2

Especificação de classes de controle  Com relação às classes de controle, no projeto

devemos identificar a real utilidade das mesmas. – Em casos de uso simples (e.g., manutenção de dados), classes de controle não são realmente necessárias. Neste caso, classes de fronteira podem repassar os dados fornecidos pelos atores diretamente para as classes de entidade correspondentes.  Entretanto, é comum a situação em que uma classe de controle de análise ser transformada em duas ou mais classes no nível de especificação.  No refinamento de qualquer classe proveniente da análise, é possível a aplicação de padrões de projeto (design patterns) 11 3

Especificação de classes de controle  Normalmente, cada classe de controle deve ser

particionada em duas ou mais outras classes para controlar diversos aspectos da solução. – Objetivo: de evitar a criação de uma única classe com baixa coesão e alto acoplamento.  Alguns exemplos dos aspectos de uma aplicação cuja coordenação é de responsabilidade das classes de controle: – produção de valores para preenchimento de controles da interface gráfica, – autenticação de usuários, – controle de acesso a funcionalidades do sistema, etc.

11 4

Especificação de classes de controle  Um tipo comum de controlador é o

controlador de

caso de uso, responsável pela coordenação da realização de um caso de uso.  As seguintes responsabilidades são esperadas de um controlador de caso de uso: – Coordenar a realização de um caso de uso do sistema. – Servir como canal de comunicação entre objetos de fronteira

e objetos de entidade. – Se comunicar com outros controladores, quando necessário. – Mapear ações do usuário (ou atores de uma forma geral) para atualizações ou mensagens a serem enviadas a objetos de entidade. – Estar apto a manipular exceções provenientes das classes de entidades.

11 5

Especificação de classes de controle  Em aplicações WEB, é comum a prática de utilizar outro tipo de   



objeto controlador chamado front controller (FC). Um FC é um controlador responsável por receber todas as requisições de um cliente. O FC identifica qual o controlador (de caso de uso) adequado para processar a requisição, e a despacha para ele. Sendo assim, um FC é um ponto central de entrada para as funcionalidades do sistema. – Vantagem: mais fácil controlar a autenticação dos usuários. O FC é um dos padrões de projeto do catálogo J2EE – http://java.sun.com/blueprints/corej2eepatterns/Patterns/Fron tController.html

11 6

Especificação de outras classes  Além do refinamento de classes preexistentes,

diversas outros aspectos demanda a identificação de novas classe durante o projeto. – Persistência de objetos – Distribuição e comunicação (e.g., RMI, CORBA, DCOM, WEB) – Autenticação/Autorização – Logging – Configurações – Threads – Classes para testes (Test Driven Development) – Uso de bibliotecas, componentes e frameworks  Conclusão: a tarefa de identificação (reuso?) de classes não termina na análise.

11 7

Projeto de classes :

11 8