VEREMOS QUE A INTERFACE PUBLIC DE UMA CLASSE ESTABELECE UM CONTRATO PARA OS PROGRAMADORES QUE USARÃO A CLASSE E QUE A INTERFACE PROTECTED ESTABELECE UM CONTRATO PARA OS PROGRAMADORES QUE ESTENDERÃO A CLASSE
TODO ALGORITMO DE ORDENAÇÃO TEM QUE ACESSAR OS DADOS PARA FAZER A ORDENAÇÃO
AS OPERAÇÕES IMPORTANTES SÃO COMPARAÇÕES E TROCAS, AS QUAIS QUEREMOS CONTAR
PODEMOS ESCREVER UMA CLASSE ABSTRATA PARA AJUDAR
UM ALGORITMO DE ORDENAÇÃO GENÉRICO NÃO PODE SER ESCRITO PORQUE AS OPERAÇÕES QUE SERÃO USADAS PARA ORDENAR DEPENDEM DAS CLASSES ESTENDIDAS E QUE FARÃO A ORDENAÇÃO
SEGUE UMA CLASSE OrdenaDouble QUE ORDENA UM ARRAY DE DOUBLES E QUE CONTABILIZA O NÚMERO DE TROCAS, COMPARAÇÕES E TESTES
UMA CLASSE MetricasDeOrdenacao AJUDA A MANTER AS ESTATÍSTICAS DA ORDENAÇÃO
abstract class OrdenaDouble { private double[] valores; private MetricasDeOrdenacao metricasAtuais = new MetricasDeOrdenacao(); /** chamado para fazer a ordenacao */ public final MetricasDeOrdenacao ordena( double[] dados ) { valores = dados; metricasAtuais.init(); facaOrdenacao(); return pegaMetricas(); } public final MetricasDeOrdenacao pegaMetricas() { return (MetricasDeOrdenacao)metricasAtuais.clone(); } protected final int pegaTamanhoDados() { return valores.length; } /** Para que as classes derivadas possam acessar os elementos */ protected final double acessa( int i ) { metricasAtuais.contaAcessos++; return valores[i]; } /** Para que as classes derivadas possam comparar elementos */ protected final int compara( int i, int j ) { metricasAtuais.contComparacoes++; if( valores[i] == valores[j] ) { return 0; } else { return (valores[i] < valores[j] ? -1 : 1 ); } } /** Para que classes derivadas possam trocar elementos */ protected final int troca( int i, int j ) { metricasAtuais.contTrocas++; double temp = valores[i]; valores[i] = valores[j]; valores[j] = temp; } /** Classes derivadas usam isso -- usado por ordena */ protected abstract void facaOrdenacao(); }
A CLASSE DEFINE CAMPOS PARA MANTER O ARRAY DE VALORES A ORDENAR (valores) E UMA REFERÊNCIA A UM OBJETO DE MÉTRICAS (metricasAtuais) PARA RASTREAR AS OPERAÇÕES MEDIDAS
PARA GARANTIR QUE AS MÉTRICAS ESTÃO CORRETAS, A CLASSE OrdenaDouble PROVÊ ROTINAS PARA USO PELAS CLASSES ESTENDIDAS DE ORDENAÇÃO QUANDO ELAS PRECISAM EXAMINAR, TROCAR OU COMPARAR VALORES
QUANDO VOCÊ PROJETA UMA CLASSE, VOCÊ PODE DECIDIR SE VAI CONFIAR NAS CLASSES ESTENDIDAS OU NÃO
OrdenaDouble NÃO CONFIAS NAS CLASSES ESTENDIDAS
ESSA É A MELHOR POLÍTICA PARA CLASSES QUE SERÃO ESTENDIDAS (MESMO QUE SEJA POR VOCÊ MESMO!) PORQUE EVITA BUGS
NESSE EXEMPLO PARTICULAR, EVITA TAMBÉM QUE UM PROGRAMADOR ESPERTO DRIBLE O CADAFALSO PARA FICAR COM MÉTRICAS (APARENTEMENTE) MELHORES
OrdenaDouble RESTRINGE O ACESSO A CADA MEMBRO MANTENDO-O NO NÍVEL CORRETO
ELA USA final PARA CADA MÉTODO NÃO ABSTRATO
PARTE DO CONTRATO QUE A CLASSE TEM É DE MANTER A INTEGRIDADE DAS MÉTRICAS
MÉTODOS FINAIS EVITA QUE UMA CLASSE DERIVADA FAÇA OVERRIDE PARA MUDAR SEU COMPORTAMENTO
COMO EFEITO COLATERAL, PERMITE QUE O COMPILADOR DEIXE O CÓDIGO MAIS RÁPIDO
OBJETOS DA CLASSE MetricasDeOrdenacao DESCREVEM O CUSTO DE UMA EXECUÇÃO DE ORDENAÇÃO
TEM 3 CAMPOS PÚBLICOS QUE SÃO NÃO SÃO ESCONDIDOS ATRÁS DE MÉTODOS "ACCESSOR", JÁ QUE A ÚNICA TAREFA DA CLASSE É DE COMUNICAR SEUS VALORES
OrdenaDouble.pegaMetricas RETORNA UMA CÓPIA DOS DADOS DE FORMA A NÃO RETORNAR UMA REFERÊNCIA PARA SEUS DADOS INTERNOS
ISSO EVITA QUE O CÓDIGO QUE CRIA OBJETOS DO TIPO OrdenaDouble E O CÓDIGO DAS CLASSES ESTENDIDAS ALTEREM OS DADOS
A CLASSE MetricasDeOrdenacao SEGUE
final class MetricasDeOrdenacao implements Cloneable { public long contAcessos, // acessos simples contComparacoes, // comparacao de dois elementos contTrocas; // troca de dois elementos public void init() { contAcessos = contComparacoes = contTrocas = 0; } public String toString() { return contAcessos + " acessos " + contComparacoes + " comparacoes " + contTrocas + " trocas"; } /** Essa classe suporta clone */ public Object clone() { try { return super.clone(); // mecanismo default funciona } catch( CloneNotSupportedException e ) { // nao pode ocorrer: this e Object permitem clone throw new InternalError( e.toString() ); } } }
A SEGUINTE CLASSE ESTENDE OrdenaDouble
É UM ALGORITMO SIMPLES (ORDENAÇÃO POR SELEÇÃO) USADO AQUI DEVIDO À SUA SIMPLICIDADE
class OrdenaPorSelecao extends OrdenaDouble { protected void facaOrdenacao() { for( int i = 0; i < pegaTamanhoDados(); i++ ) { for( int j = i + 1; j < pegaTamanhoDados(); j++ ) { if( compara( i, j ) > 0 ) { troca( i, j ); } } } } }
AGORA, PODEMOS ESCREVER O RESTO DO CADAFALSO
O CÓDIGO ABAIXO PRECISA SER ALTERADO MUITO POUCO PARA TESTAR VÁRIOS ALGORITMOS DE ORDENAÇÃO
NESTE CASO, ELE TESTA OrdenaPorSelecao
public class TestaOrdenacao { static double[] dadosDeTeste = { 0.3, 1.3e-2, 7.9, 3.17, }; static public void main( String[] args ) { OrdenaDouble ordSelecao = new OrdenaPorSelecao(); MetricasDeOrdenacao metricas = ordSelecao.ordena( dadosDeTeste ); System.out.println( "Metricas: " + metricas ); for( int i = 0; i < dadosDeTeste.length; i++ ) { System.out.println( "\t" + dadosDeTeste[i] ); } } }
UMA POSSÍVEL SAÍDA DO PROGRAMA ACIMA SERIA:
Metricas: 0 acessos 6 comparacoes 2 trocas 0.013 0.3 3.17 7.9
PROJETAMOS A INTERFACE PROTECTED DE OrdenaDouble PARA PERMITIR UM ACESSO MAIS ÍNTIMO AOS DADOS DO OBJETO MAS APENAS PARA ACESSAR AS COISAS QUE QUEREMOS
A PARTE PÚBLICA DA CLASSE PODE SER USADO PELO CÓDIGO QUE MEDE O DESEMPENHO DO ALGORITMO
AS MÉTRICAS OBTIDAS EM TestaOrdenacao SÃO READ-ONLY (ATRAVÉS DE toString, POR EXEMPLO)
A ROTINA ordena GARANTE QUE AS MÉTRICAS SEJAM INICIALIZADAS ANTES DE USADAS
FAZER COM QUE facaOrdenacao SEJA PROTECTED GARANTE QUE O CÓDIGO DE TESTE A CHAME APENAS INDIRETAMENTE ATRAVÉS DA ROTINA PÚBLICA ordena
PARA TESTAR O CÓDIGO, SÓ PODEMOS CHAMAR A ROTINA DE ORDENAÇÃO E EXAMINAR OS RESULTADOS
O RESTO DA CLASSE ESTÁ ESCONDIDO
A PARTE PROTECTED DA CLASSE FOI PROJETADO PARA GARANTIR UM EXECUÇÃO COM MEDIÇÕES CORRETAS
O ALGORITMO DE ORDENAÇÃO PODE ACESSAR E MODIFICAR OS DADOS SENDO ORDENADOS
O CONTRATO FORNECE UM LUGAR (facaOrdenacao) PARA COLOCAR O CÓDIGO DE ORDENAÇÃO QUE SERÁ MEDIDO
A ROTINA DE ORDENAÇÃO SÓ PODE ACESSAR OS DADOS ATRAVÉS DAS ROTINAS QUE PERMITIRÃO A MEDIÇÃO
EXEMPLO: PARA EVITAR CHAMAR compara, A ROTINA SERIA FORÇADA A USAR acessa QUE TAMBÉM CONTABILIZA ACESSOS
pegaMetricas RETORNA UM CLONE DAS MÉTRICAS PARA QUE UMA IMPLEMENTAÇÃO DE ORDENAÇÃO NÃO POSSA ALTERAR OS VALORES
OS DADOS QUE DEVEM SER ESCONDIDOS SÃO PRIVADOS
SÃO OS DADOS DO ARRAY E AS MÉTRICAS
ELES NÃO PODEM SER ACESSADOS DIRETA OU INDIRETAMENTE