UNIVERSIDADE DO ESTADO DO RIO DE JANEIRO
Projeto de Sistemas III
Professor Júlio
Alunos:
Danielle Costa Lopes Gonçalves da Silva.
Maurício dos Reis Brum.
Anderson Pereira Bastos.
Paulo Roberto Moura de Carvalho.
Trabalho sobre o padrão Strategy
Intenção
Definir uma família de algoritmos de ordenação de um arranjo, encapsular cada um deles e
torna-los intercambiáveis. Strategy permite que o algoritmo varie independentemente dos clientes
que o utilizam.
Sinônimo
Policy.
Motivação
Existem muitos algoritmos para ordenar uma lista. Implementar no corpo dos clientes cada um
deles é contraproducente:
•
•
•
Os clientes se tornariam muito grandes se embutissem em si mesmos a implementação de
cada um deles.
Algoritmos de ordenação são ótimos com certos arranjos quando comparado com os demais,
assim, seria interessante manter uma biblioteca com os diferentes algoritmos à disposição
dos clientes.
Adicionar novos algoritmos ou fazer manutenção nos existentes requereria um esforço extra
para localizar onde estão implementados cada algoritmo.
Estes problemas podem ser evitados se forem definidas classes que encapsulam os diferentes
algoritmos de ordenação.
Ordenação é o responsável pela ordenação de uma lista, que pode ser pelo nome do aluno ou
pela nota. As estratégias de ordenação não são implementadas por Ordenação, mas sim pelas
subclasses da interface Sort. As subclasses de Sort implementam diferentes estratégias:
•
•
•
•
BubbleSort: Estratégia de fácil manutenção e de baixo consumo de memória, indicado para
arranjos pequenos.
SelectionSort: Estratégia de fácil manutenção, cerca de 40% mais eficiente que
BubbleSort, porém consome muito mais memória. Também indicado para arranjos
pequenos.
InsertionSort: Muito eficiente para arranjos quase ordenados, por exemplo uma tabela já
ordenada que recebe um novo registro ou tem um registro modificado.
Cada uma das estratégias acima tem duas subclasses: uma para ordenar pelo nome e outra
pela nota. O fato de ambos os tipos de dados serem de natureza diferente requer que seja
criada uma estratégia para cada caso pois a forma com que se compara strings difere de
quando se compara números de ponto flutuante. Pelo menos, em Java, os operadores de
comparação atuam em nível de ponteiro para strings. “nome” == “nome” quase sempre
retorna falso em Java.
Uma Ordenação mantém uma referência para um objeto da classe Sort. Sempre que um Cliente
solicita a ordenação do seu vetor a ela, Ordenação repassa a tarefa para o seu objeto ordenador
(classe Sort). O Cliente especifica a estratégia quando constrói o objeto Ordenação, assim, o
Cliente tem a liberdade de ter qualquer número de ordenadores, cada qual com uma estratégia
diferente.
Aplicabilidade
Vide página 293>.
Estrutura
Vide página 294>.
Participantes
•
•
•
•
Strategy (Sort)
ConcreteStrategy(BubbleSortPorNome,
BubbleSortPorNota,
SelectionSortPorNome,
SelectionSortPorNota, InsertionSortPorNome, InsertionSortPorNota)
Context (Ordenacao)
A classe Janela faz o papel de Cliente.
Colaborações
Vide página 294>.
Conseqüências
Vide página 294>.
Implementação
1. Definindo as interfaces de Sort e Ordenação. Ordenação chama o método ordenar() do
seu objeto Sort (ordenador), passando como parâmetro uma referência à lista a ser ordenada.
2. Cliente. O cliente passa uma referência à lista a ser ordenada quando constrói o seu objeto
Ordenacao.
Exemplos de código
O Cliente instancia um objeto Ordenação, passando como parâmetros a lista e um objeto de uma
subclasse de Sort. A seguir tudo que o cliente tem a fazer é chamar a operação getListaOrdenada()
de Ordenação toda vez que necessitar de obter uma cópia ordenada de sua lista.
//======================================Janela.java========================================
//====Foram omitidos trechos de código irrelevantes para a compreensão do padrão.
/*
* Janela.java
*
* Created on 24 de Agosto de 2005, 13:45
*/
public class Janela extends javax.swing.JFrame {
private Lista lista;
(…)
private void btnOrdenarComInsertionSortActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_btnOrdenarComInsertionSortActionPerformed
//defino qual ordenacao vou usar
estrategia.Sort is;
if(this.radioPorNome.isSelected())
is = new estrategia.InsertionSortPorNome();
else
is = new estrategia.InsertionSortPorNota();
//construo a Ordenacao passando a lista e o ordenador escolhido
try{
estrategia.Ordenacao ordenacao = new estrategia.Ordenacao((Lista)this.lista.clone(),
is);
Lista lista_ordenada = ordenacao.getListaOrdenada();
(...)
}//GEN-LAST:event_btnOrdenarComInsertionSortActionPerformed
private void btnOrdenarComSelectionSortActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_btnOrdenarComSelectionSortActionPerformed
//defino qual ordenacao vou usar
estrategia.Sort ss;
if(this.radioPorNome.isSelected())
ss = new estrategia.SelectionSortPorNome();
else
ss = new estrategia.InsertionSortPorNota();
//construo a Ordenacao passando a lista e o ordenador escolhido
try{
estrategia.Ordenacao ordenacao = new estrategia.Ordenacao((Lista)this.lista.clone(),
ss);
Lista lista_ordenada = ordenacao.getListaOrdenada();
(...)
}//GEN-LAST:event_btnOrdenarComSelectionSortActionPerformed
private void btnOrdenarComBubbleSortActionPerformed(java.awt.event.ActionEvent evt) {//GENFIRST:event_btnOrdenarComBubbleSortActionPerformed
//defino qual ordenacao vou usar
estrategia.Sort bbs;
if(this.radioPorNome.isSelected())
bbs = new estrategia.BubbleSortPorNome();
else
bbs = new estrategia.BubbleSortPorNota();
//construo a Ordenacao passando a lista e o ordenador escolhido
try{
estrategia.Ordenacao ordenacao = new estrategia.Ordenacao((Lista)this.lista.clone(),
bbs);
Lista lista_ordenada = ordenacao.getListaOrdenada();
(...)
}//GEN-LAST:event_btnOrdenarComBubbleSortActionPerformed
(...)
private javax.swing.JButton btnOrdenarComBubbleSort;
private javax.swing.JButton btnOrdenarComInsertionSort;
private javax.swing.JButton btnOrdenarComSelectionSort;
(...)
}
Ordenação ao ser instanciado recebe uma referência ao Cliente e a um objeto de uma das subclasses
de Sort. Toda vez que o Cliente requer que uma ordenação seja feita, Ordenação, que tem uma uma
referência à lista do cliente, produz uma cópia da lista (em se desejando manter a lista original) e a
repassa como parâmetro para o objeto ordenador (Sort), chamando sua operação ordenar().
//======================================Ordenacao.java========================================
package estrategia;
import java.util.Vector;
public class Ordenacao {
private programa.Lista ref_lista; //o cliente vai passar uma referência à lista
private Sort ordenador;
public Ordenacao(programa.Lista plista, Sort qual_sort) {
//o cliente constrói a Ordencao passando por parâmetros
//uma referência ao objeto lista
//uma referência a uma subclasse concreta de Sort
//que vai determinar qual o algoritmo de ordenação a ser usado
//e por qual campo (se é por nome ou por nota)
ref_lista = plista;
ordenador = qual_sort;
}
public programa.Lista getListaOrdenada() {
//obtem uma copia da lista, pois quero preservar a original
//programa.Lista copia_lista = new programa.Lista();
//copia_lista.setLista((Vector)ref_lista.getLista().clone());
ordenador.ordenar(ref_lista);
//((programa.EntradaLista)copia_lista.getLista().get(0)).setStrNome("zzzzz");
return ref_lista;
}
}
A interface Sort. A operação ordenar() coloca em ordem crescente os elementos da lista cuja
referência é passada como parâmetro.
//======================================Sort.java========================================
package estrategia;
public abstract class Sort {
public abstract void ordenar(programa.Lista lista);
}
As subclasses de Sort(). Elas implementam a operação ordenar(), implementando-a de acordo com
a estratégia a que elas se propõem. A rigor todas as sublcasses de Sort fazem a mesma coisa. A
diferença reside apenas nas diferenças de desempenho, consumo de memória, facilidade de
manutenção nas diversas circunstâncias e por qual informação se deseja ordenar a lista.
//======================================BubbleSort.java========================================
package estrategia;
public abstract class BubbleSort extends Sort {
public abstract void ordenar(programa.Lista lista);
}
//======================================BubbleSortPorNome.java=================================
package estrategia;
public class BubbleSortPorNome extends BubbleSort{
public void ordenar(programa.Lista lista) {
//algoritmo original, com vetor de char
//
for (int i = vetor.length; --i >= 0; )
//
for (int j = 0; j < i; j++)
//
if (vetor[j] > vetor[j+1]) {
//
char temp = vetor[j];
//
vetor[j] = vetor[j + 1];
//
vetor[j + 1] = temp;
//
}
for (int i = lista.getLista().size(); --i >= 0; )
for (int j = 0; j < i; j++){
programa.EntradaLista el1 = (programa.EntradaLista)(lista.getLista().get(j));
programa.EntradaLista el2 = (programa.EntradaLista)(lista.getLista().get(j+1));
if(el1.getStrNome().compareToIgnoreCase(el2.getStrNome()) > 0) {
String tempNome = el1.getStrNome();
float tempNota = el1.getFltNota();
el1.setStrNome(el2.getStrNome());
el1.setFltNota(el2.getFltNota());
el2.setStrNome(tempNome);
el2.setFltNota(tempNota);
}
}
}
public BubbleSortPorNome() {
}
}
//======================================BubbleSortPorNota.java=================================
package estrategia;
public class BubbleSortPorNota extends BubbleSort{
public void ordenar(programa.Lista lista) {
//algoritmo original, com vetor de char
//
for (int i = vetor.length; --i >= 0; )
//
for (int j = 0; j < i; j++)
//
if (vetor[j] > vetor[j+1]) {
//
char temp = vetor[j];
//
vetor[j] = vetor[j + 1];
//
vetor[j + 1] = temp;
//
}
for (int i = lista.getLista().size(); --i >= 0; )
for (int j = 0; j < i; j++){
programa.EntradaLista el1 = (programa.EntradaLista)(lista.getLista().get(j));
programa.EntradaLista el2 = (programa.EntradaLista)(lista.getLista().get(j+1));
if(el1.getFltNota() > el2.getFltNota()) {
String tempNome = el1.getStrNome();
float tempNota = el1.getFltNota();
el1.setStrNome(el2.getStrNome());
el1.setFltNota(el2.getFltNota());
el2.setStrNome(tempNome);
el2.setFltNota(tempNota);
}
}
}
public BubbleSortPorNota() {
}
}
//======================================InsertionSort.java========================================
package estrategia;
public abstract class InsertionSort extends Sort {
public abstract void ordenar(programa.Lista lista);
}
//======================================InsertionSortPorNome.java=================================
package estrategia;
public class InsertionSortPorNome extends InsertionSort{
public InsertionSortPorNome() {
}
public void ordenar(programa.Lista lista) {
//algoritmo original, com vetor de char
//
for (int i = 1; i < vetor.length; i++) {
//
int j = i;
//
char B = vetor[i];
//
while ((j > 0) && (vetor[j-1] > B)) {
//
vetor[j] = vetor[j-1];
//
j--;
//
}
//
vetor[j] = B;
//
}
for (int i = 1; i < lista.getLista().size(); i++) {
int j = i;
programa.EntradaLista B = new programa.EntradaLista("", 0f);
B.setStrNome(((programa.EntradaLista)lista.getLista().get(i)).getStrNome());
B.setFltNota(((programa.EntradaLista)lista.getLista().get(i)).getFltNota());
while ((j > 0) && (((programa.EntradaLista)lista.getLista().get(j1)).getStrNome().compareToIgnoreCase(B.getStrNome()) > 0)) {
programa.EntradaLista el1 = (programa.EntradaLista)lista.getLista().get(j-1);
programa.EntradaLista el2 = (programa.EntradaLista)lista.getLista().get(j);
el2.setStrNome(el1.getStrNome());
el2.setFltNota(el1.getFltNota());
j--;
}
((programa.EntradaLista)lista.getLista().get(j)).setStrNome(B.getStrNome());
((programa.EntradaLista)lista.getLista().get(j)).setFltNota(B.getFltNota());
}
}
}
//======================================InsertionSortPorNota.java=================================
package estrategia;
public class InsertionSortPorNota extends InsertionSort{
public InsertionSortPorNota() {
}
public void ordenar(programa.Lista lista) {
//algoritmo original, com vetor de char
//
for (int i = 1; i < vetor.length; i++) {
//
int j = i;
//
char B = vetor[i];
//
while ((j > 0) && (vetor[j-1] > B)) {
//
vetor[j] = vetor[j-1];
//
j--;
//
}
//
vetor[j] = B;
//
}
for (int i = 1; i < lista.getLista().size(); i++) {
int j = i;
programa.EntradaLista B = new programa.EntradaLista("", 0f);
B.setStrNome(((programa.EntradaLista)lista.getLista().get(i)).getStrNome());
B.setFltNota(((programa.EntradaLista)lista.getLista().get(i)).getFltNota());
while ((j > 0) && (((programa.EntradaLista)lista.getLista().get(j-1)).getFltNota() >
B.getFltNota())) {
programa.EntradaLista el1 = (programa.EntradaLista)lista.getLista().get(j-1);
programa.EntradaLista el2 = (programa.EntradaLista)lista.getLista().get(j);
el2.setStrNome(el1.getStrNome());
el2.setFltNota(el1.getFltNota());
j--;
}
((programa.EntradaLista)lista.getLista().get(j)).setStrNome(B.getStrNome());
((programa.EntradaLista)lista.getLista().get(j)).setFltNota(B.getFltNota());
}
}
}
//======================================SelectionSort.java========================================
package estrategia;
public abstract class SelectionSort extends Sort {
public abstract void ordenar(programa.Lista lista);
}
//======================================SelectionSortPorNome.java=================================
package estrategia;
public class SelectionSortPorNome extends SelectionSort{
public void ordenar(programa.Lista lista) {
//algoritmo original usando vetor de char
// varre o vetor, procurando pelo próximo valor máximo
// e trocando-o com o primeiro elemento da parte não ordenada do vetor
//
for (int i = 0; i < vetor.length - 1; i++ )
//
{
//
int minIndice = i;
// indice do menor valor
//
char min = vetor[minIndice];
// o menor valor
//
// encontrar o menor valor da parte não ordenada do vetor.
//
for ( int j = i + 1; j < vetor.length; j++ )
//
{
//
// If this element is less than min it becomes the min.
//
// se o elemento atual é menor do que o mínimo, ele se torna o mínimo
//
if ( vetor[j] < min )
//
{
//
minIndice = j;
//
min = vetor[minIndice];
//
}
//
}
//
//troca o 1o elemento na parte não ordenada
//
// com o item de menor valor (mesmo que o 1o item já seja o menor)
//
char T = vetor[minIndice];
//
vetor[minIndice] = vetor[i];
//
vetor[i] = T;
//
}
for (int i = 0; i < lista.getLista().size() - 1; i++ )
{
int minIndice = i;
// indice do menor valor
//o menor valor
String strMinNome =
((programa.EntradaLista)lista.getLista().get(minIndice)).getStrNome();
// encontrar o menor valor da parte não ordenada da lista.
for ( int j = i + 1; j < lista.getLista().size(); j++ )
{
// se o elemento atual é menor do que o mínimo, ele se torna o mínimo
if (
((programa.EntradaLista)lista.getLista().get(j)).getStrNome().compareToIgnoreCase(strMinNome) < 0 )
{
minIndice = j;
strMinNome =
((programa.EntradaLista)lista.getLista().get(minIndice)).getStrNome();
}
}
//troca o 1o elemento na parte não ordenada
// com o item de menor valor (mesmo que o 1o item já seja o menor)
String strTmpNome =
((programa.EntradaLista)lista.getLista().get(minIndice)).getStrNome();
float fltTmpNota =
((programa.EntradaLista)lista.getLista().get(minIndice)).getFltNota();
((programa.EntradaLista)lista.getLista().get(minIndice)).setStrNome(((programa.EntradaLista)lista.ge
tLista().get(i)).getStrNome());
((programa.EntradaLista)lista.getLista().get(minIndice)).setFltNota(((programa.EntradaLista)lista.ge
tLista().get(i)).getFltNota());
((programa.EntradaLista)lista.getLista().get(i)).setStrNome(strTmpNome);
((programa.EntradaLista)lista.getLista().get(i)).setFltNota(fltTmpNota);
}
}
public SelectionSortPorNome() {
}
}
//======================================SelectionSortPorNota.java=================================
package estrategia;
public class SelectionSortPorNota extends SelectionSort{
public void ordenar(programa.Lista lista) {
//algoritmo original usando vetor de char
// varre o vetor, procurando pelo próximo valor máximo
// e trocando-o com o primeiro elemento da parte não ordenada do vetor
//
for (int i = 0; i < vetor.length - 1; i++ )
//
{
//
int minIndice = i;
// indice do menor valor
//
char min = vetor[minIndice];
// o menor valor
//
// encontrar o menor valor da parte não ordenada do vetor.
//
for ( int j = i + 1; j < vetor.length; j++ )
//
{
//
// If this element is less than min it becomes the min.
//
// se o elemento atual é menor do que o mínimo, ele se torna o mínimo
//
if ( vetor[j] < min )
//
{
//
minIndice = j;
//
min = vetor[minIndice];
//
}
//
}
//
//troca o 1o elemento na parte não ordenada
//
// com o item de menor valor (mesmo que o 1o item já seja o menor)
//
char T = vetor[minIndice];
//
vetor[minIndice] = vetor[i];
//
vetor[i] = T;
//
}
for (int i = 0; i < lista.getLista().size() - 1; i++ )
{
int minIndice = i;
// indice do menor valor
//o menor valor
float fltMinNota =
((programa.EntradaLista)lista.getLista().get(minIndice)).getFltNota();
// encontrar o menor valor da parte não ordenada da lista.
for ( int j = i + 1; j < lista.getLista().size(); j++ )
{
// se o elemento atual é menor do que o mínimo, ele se torna o mínimo
if ( ((programa.EntradaLista)lista.getLista().get(j)).getFltNota() < fltMinNota)
{
minIndice = j;
fltMinNota =
((programa.EntradaLista)lista.getLista().get(minIndice)).getFltNota();
}
}
//troca o 1o elemento na parte não ordenada
// com o item de menor valor (mesmo que o 1o item já seja o menor)
String strTmpNome =
((programa.EntradaLista)lista.getLista().get(minIndice)).getStrNome();
float fltTmpNota =
((programa.EntradaLista)lista.getLista().get(minIndice)).getFltNota();
((programa.EntradaLista)lista.getLista().get(minIndice)).setStrNome(((programa.EntradaLista)lista.ge
tLista().get(i)).getStrNome());
((programa.EntradaLista)lista.getLista().get(minIndice)).setFltNota(((programa.EntradaLista)lista.ge
tLista().get(i)).getFltNota());
((programa.EntradaLista)lista.getLista().get(i)).setStrNome(strTmpNome);
((programa.EntradaLista)lista.getLista().get(i)).setFltNota(fltTmpNota);
}
}
public SelectionSortPorNota() {
}
}
Usos conhecidos
Vide página 299>.
Padrão relacionado
Vide página 300>.
>
Gamma, E; Helm, R.; Johnson, R; Vlissides, J.
objetos. Ed. Bookman. Porto Alegre, 2005.
>
Gamma, E; Helm, R.; Johnson, R; Vlissides, J.
objetos. Ed. Bookman. Porto Alegre, 2005.
>
Gamma, E; Helm, R.; Johnson, R; Vlissides, J.
objetos. Ed. Bookman. Porto Alegre, 2005.
>
Gamma, E; Helm, R.; Johnson, R; Vlissides, J.
objetos. Ed. Bookman. Porto Alegre, 2005.
>
Gamma, E; Helm, R.; Johnson, R; Vlissides, J.
objetos. Ed. Bookman. Porto Alegre, 2005.
>
Gamma, E; Helm, R.; Johnson, R; Vlissides, J.
objetos. Ed. Bookman. Porto Alegre, 2005.
Padrões de Projeto – Soluções reutilizáveis de software orientado a
Padrões de Projeto – Soluções reutilizáveis de software orientado a
Padrões de Projeto – Soluções reutilizáveis de software orientado a
Padrões de Projeto – Soluções reutilizáveis de software orientado a
Padrões de Projeto – Soluções reutilizáveis de software orientado a
Padrões de Projeto – Soluções reutilizáveis de software orientado a
Download

Trabalho - PUC-Rio