Lab2 Tiago Porto

aluno: Tiago Porto
ano/sem: 2008/2o.
data do laboratório (6) : 03/09/2008

Introdução

Esse segundo laboratório é uma extensão dos conceitos do primeiro.

Até o primeiro laboratório a aplicação não tinha muita utilidade para um usuário que não tivesse conhecimento de programação Java e orientação a objetos. Isto mudou. Foi criado uma classe para maior interatividade com o programa.

Para deixar bem delimitado o comportamento das subclasses de Aluno, evitando um grande número de subclasses, foi criada uma classe Comportamento, que define o comportamento de dos varios tipos de aluno. Desse modo, há um encapsulamento e desacoplamento da classe Aluno com suas subclasses.

O conceito de genéricos foi utilizado na lista de relatório.

Desenvolvimento

Algumas classes permaneceram inalteradas em relação ao primeiro laboratório:

Classe Professor

import java.util.*; /* Random() */
 
public class Professor {
    RelaQueue queue;
    public Professor(RelaQueue queue){
        /* Metodo construtor da classe Professor*/
        this.queue = queue;
    }
    private double corrigirRelatorio(Relatorio rela){
        /* Calculo da nota de um relatorio */
        double nota = ( rela.getQualidade() + rela.getOriginalidade() + this.fatorAleatorioDe0a1() ) / 3 * 10;
        return nota;
    }
    public void corrigirRelatorios(){
        Relatorio rela = queue.dequeue();
        /* Corrige os relatorios ate a pilha ficar vazia */
        while (rela!=null){
            System.out.println(rela.getAluno().getNome()+": "+corrigirRelatorio(rela));
            rela = queue.dequeue();
        }
    }
    private double fatorAleatorioDe0a1(){
        /* Metodo que gera um numero aletorio de 0 a 1 */
        Random generator = new Random();
        double r = generator.nextDouble();
        return r;
    }   
}

Classe SafoPreguicoso
O nome foi alterado de AlunoSafoPreguicoso para SafoPreguicoso.

import java.util.*; // Ramdon();
 
public class SafoPreguicoso extends Comportamento{
    double inteligencia = 1;
    public SafoPreguicoso(Aluno aluno){
        super(aluno);
    }
    public double getInteligencia(){
        return inteligencia;
    }
    public double getDedicacao(){
        return generateRandomDe0aMeio();
    }
    private double generateRandomDe0aMeio(){
        /* Metodo que retorna um valor aleatorio de 0 a 0.5 */
        Random generator = new Random();
        double r = generator.nextDouble();
        return r * 0.5;
    }
}

Classe Esforcado
O nome foi alterado de AlunoEsforcado para Esforcado.

public class Esforcado extends Comportamento{
    double inteligencia = 0.5;
    double dedicacao = 1;
    public Esforcado(Aluno aluno){
        super(aluno);
    }
    public double getInteligencia(){
        return inteligencia;
    }
    public double getDedicacao(){
        return dedicacao;
    }
}

Classe Relatorio

public class Relatorio{
    double qualidade;
    double originalidade;
    Aluno aluno;
    public Relatorio(double qualidade, double originalidade, Aluno aluno){
        /* Metodo construtor da classe Relatorio */
        this.qualidade = qualidade;
        this.originalidade = originalidade;
        this.aluno = aluno;       
    }
    public double getQualidade(){
        return qualidade;
    }
    public double getOriginalidade(){
        return originalidade;
    }
    public Aluno getAluno(){
        return aluno;
    }
}

Classe Aluno
A classe aluno deixou de ser abstrata.
Ela tem uma variável interna comportamento, que determina qual o comportamento de um aluno.
Aluno delega os métodos getInteligencia() e getDedicacao() para o seu objeto comportamento. Ela também tem um método público setComportamento(Comportamento comportamento) que define qual é o comportamento do aluno.
Os demais métodos de aluno (getNome(), etc) permanecem inalterados.
No momento da criação, Aluno já tem um comportamento definido: Esforcado.

public class Aluno{
    int conhecimento = 0;
    String nome = new String();
    RelaQueue queue;
    Comportamento comportamento;
    public Aluno(String nome, RelaQueue queue){
        /* Metodo construtor da classe Aluno */
        this.nome = nome;
        this.queue = queue;
        comportamento = new Esforcado(this);
    }
    public void fazEEntregaRelatorio(){
        /* Calculo dos atributos do relatorio */
        double qualidade = (2 * this.getDedicacao() + 1 * this.getInteligencia() ) / 3 ;
        double originalidade = (1 * this.getDedicacao() + 2 * this.getInteligencia() ) / 3 ;
        /* Criacao de um novo relatorio */
        Relatorio rela = new Relatorio(qualidade, originalidade, this);
        /* Empilha o relatorio criado */
        queue.queue(rela);
    }
    public int getConhecimento(){
        return conhecimento;
    }
    /* getInteligencia() e getDedicacao() deixaram de ser metodos abstratos */
    /* Aluno irá delegar os métodos getInteligencia() e getDedicacao() 
     * para o seu objeto comportamento */
    public double getInteligencia(){
        return comportamento.getInteligencia();    
    }
    public double getDedicacao(){
        return comportamento.getDedicacao();    
    }
    public String getNome(){
        return nome;
    }
    public void setComportamento(Comportamento comportamento) throws Exception {
        this.comportamento = comportamento;    
    }
}

Aproveitando que a aplicação ficou mais robusta, definiu-se outros comportamentos, além de SafoPreguicoso e Esforcado.

Classe Summa
Tem a inteligência e dedicação sempre 1.

public class Summa extends Comportamento{
    double inteligencia = 1;
    double dedicacao = 1;
    public Summa(Aluno aluno){
        super(aluno);        
    }
    public double getInteligencia(){
        return inteligencia;
    }
    public double getDedicacao(){
        return dedicacao;
    }
}

Classe Imprevisivel
Tem a dedicacao e inteligencia como aleatórios variando de 0 a 1.

import java.util.*; // Ramdon();
 
public class Imprevisivel extends Comportamento{
    public Imprevisivel(Aluno aluno){
       super(aluno);
    }
    public double getInteligencia(){
        return generateRandomDe0a1();
    }
    public double getDedicacao(){
        return generateRandomDe0a1();
    }
    private double generateRandomDe0a1(){
        /* Metodo que retorna um valor aleatorio de 0 a 1 */
        Random generator = new Random();
        double r = generator.nextDouble();
        return r;
    }
}

Classe Pemba
Tem a inteligência e dedicação como aleatórios variando de 0 a 0.5.

import java.util.*; // Ramdon();
 
public class Pemba extends Comportamento{
    public Pemba(Aluno aluno){
        super(aluno);
    }
    public double getInteligencia(){
        return generateRandomDe0aMeio();
    }
    public double getDedicacao(){
        return generateRandomDe0aMeio();
    }
    private double generateRandomDe0aMeio(){
        /* Metodo que retorna um valor aleatorio de 0 a 0.5 */
        Random generator = new Random();
        double r = generator.nextDouble();
        return r * 0.5;
    }
}

Classe Burro
Tem a dedicacao e inteligencia sempre 0.

public class Burro extends Comportamento{
    double inteligencia = 0;
    double dedicacao = 0;
    public double getInteligencia(){
        return inteligencia;
    }
    public double getDedicacao(){
        return dedicacao;
    }
    public Burro(Aluno aluno){
        super(aluno);    
    }
}

Classe Queue<Relatorios>
Utilizando genéricos, criou-se uma fila cujo conteúdo interno não é restrito a objetos do tipo Relatório.
Criou-se uma classe Queue<T>, de que RelaQueue é uma subclasse com o corpo do código em branco.
A finalidade de manter RelaQueue como subclasse de Queue<Relatorio> é manter a compatibilidade com o código do laborataório 1, que se utiliza da classe RelaQueue.

public class Queue<T> {
    /* A classe Object é uma classe que serve de superclasse para todas 
     * as classes existentes em Java */
    private Object[] array = new Object[10];
    private int inicio = 0;
    private int fim = 0;
    public void queue(T obj) {  
        /* Metodo que empilha um relatorio no final da pilha */
        array[fim] = obj;
        fim = (fim + 1) % 10;
    }  
    public T dequeue(){  
        if (inicio!=fim){
            T valor = (T)  array[inicio];
            inicio = (inicio + 1) % 10;
            return valor;
        } else {
            return null;
        }
    }  
}

Classe RelaQueue

public class RelaQueue extends Queue<Relatorio>{ }

Classe AlunoITA

Alunos de instituições diferentes:
Criou-se 3 subclasses de alunos, de acordo com a sua faculdade de origem: AlunoITA, AlunoUSP e AlunoUnicamp, para usar tratamento de exceções em Java (os alunos do ITA nunca podem ser burros, e os alunos da USP e Unicamp nunca serão nem Summas nem SafosPreguicosos).

public class AlunoITA extends Aluno{
    public AlunoITA(String nome, RelaQueue queue){
        super(nome, queue);           
    }
    public void setComportamento(Comportamento comportamento) throws Exception {
        if(comportamento instanceof Burro) 
            throw new Exception();
        super.setComportamento(comportamento);
    }
}

Classe AlunoUnicamp

public class AlunoUnicamp extends Aluno{
    public AlunoUnicamp(String nome, RelaQueue queue){
        super(nome, queue);        
    }
    public void setComportamento(Comportamento comportamento) throws Exception {
        if(comportamento instanceof Summa) 
            throw new Exception();
        if(comportamento instanceof SafoPreguicoso) 
            throw new Exception();
        super.setComportamento(comportamento);
    }
}

Classe AlunoUSP

public class AlunoUSP extends Aluno{
    public AlunoUSP(String nome, RelaQueue queue){
        super(nome, queue);
    }
    public void setComportamento(Comportamento comportamento) throws Exception {
        if(comportamento instanceof Summa) 
            throw new Exception();
        if(comportamento instanceof SafoPreguicoso) 
            throw new Exception();
        super.setComportamento(comportamento); 
    }
}

Resultados da Classe Teste
Pronto, agora podemos testar o programa com a classe Teste

public class Teste extends junit.framework.TestCase
{
         public void testFuncionaComoOLab1() {
             //criando os objetos
             RelaQueue queue = new RelaQueue();
             Professor prof = new Professor(queue);
 
             // O que muda em termos de interface externa neste lab,
             // é a criação dos alunos. O que mostra que o nosso código
             // está bem desacoplado e a nossa refatoração não alterou
             // o funcionamento dos outros objetos (Professor, Relatório, etc).
             Aluno aluno1 = new Aluno("John Smith", queue);
             Aluno aluno2 = new Aluno("Mark Smith", queue);
             Aluno aluno3 = new Aluno("Joseph Smith", queue);
             Aluno aluno4 = new Aluno("Robert Smith", queue);
             try {
                 aluno3.setComportamento( new SafoPreguicoso(aluno3) );
                 aluno4.setComportamento( new SafoPreguicoso(aluno4) );
            } catch (Exception e){ 
                    fail("Não deveria lançar erro!");
            }
 
            //teste de alunoesforcado
            assertEquals(0.5, aluno1.getInteligencia(), 0.01);
            assertEquals(1, aluno1.getDedicacao(), 0.01);
 
            //teste de alunosafo
            assertEquals(1.0, aluno3.getInteligencia(), 0.01);
            assertTrue(aluno3.getDedicacao() != aluno3.getDedicacao()); //deve ser randomica
            assertTrue(aluno3.getDedicacao() < 0.5);
 
            //alunos comecam a fazer os relas
            aluno1.fazEEntregaRelatorio();
 
            //roubamos o relatório do primeiro aluno para investigá-lo
            Relatorio rela1 = queue.dequeue();
            assertEquals(aluno1, rela1.getAluno());
            assertTrue(rela1.getAluno().getNome().equals("John Smith"));
            assertTrue(rela1.getQualidade() < 0.9);
            assertTrue(rela1.getQualidade() > 0.8);
            assertTrue(rela1.getOriginalidade() < 0.7);
            assertTrue(rela1.getOriginalidade() > 0.6);
 
            //os outros continuam a fazer os relas
            aluno2.fazEEntregaRelatorio();
            aluno3.fazEEntregaRelatorio();
            aluno4.fazEEntregaRelatorio();
 
            //deve exibir a coreção dos relas dos aluno2, aluno3, e aluno4, nesta ordem
            //pois "roubamos" o relatório do aluno1
            prof.corrigirRelatorios();
        }
 
        public void testOsComportamentosFuncionamComoEspecificado() {
            RelaQueue queue = new RelaQueue();
            Aluno aluno1 = new Aluno("John", queue);
            Comportamento summa = new Summa(aluno1);
            Comportamento pemba = new Pemba(aluno1);
            Comportamento imprevisivel = new Imprevisivel(aluno1);
            Comportamento safo = new SafoPreguicoso(aluno1);
            Comportamento esforcado = new Esforcado(aluno1);
            Comportamento burro = new Burro(aluno1);
 
            //teste de esforcado
            assertEquals(0.5, esforcado.getInteligencia(), 0.01);
            assertEquals(1, esforcado.getDedicacao(), 0.01);
 
            //teste de burro
            assertEquals(0.0, burro.getInteligencia(), 0.01);
            assertEquals(0.0, burro.getDedicacao(), 0.01);
 
            //teste de summa
            assertEquals(1.0, summa.getInteligencia(), 0.01);
            assertEquals(1.0, summa.getDedicacao(), 0.01);
 
            //teste de safo
            assertEquals(1.0, safo.getInteligencia(), 0.01);
            assertTrue(safo.getDedicacao() != safo.getDedicacao()); //deve ser randomica
            assertTrue(safo.getDedicacao() < 0.5);
 
            //teste de imprevisivel
            assertTrue(imprevisivel.getInteligencia() != safo.getInteligencia()); //deve ser randomica
            assertTrue(imprevisivel.getInteligencia() < 1.0);
            assertTrue(imprevisivel.getDedicacao() != safo.getDedicacao()); //deve ser randomica
            assertTrue(imprevisivel.getDedicacao() < 1.0);
 
            //teste de pemba
            assertTrue(pemba.getInteligencia() != pemba.getInteligencia()); //deve ser randomica
            assertTrue(pemba.getInteligencia() < 0.5);
            assertTrue(pemba.getDedicacao() != pemba.getDedicacao()); //deve ser randomica
            assertTrue(pemba.getDedicacao() < 0.5);
 
        }
        public void testAsSubClassesDeAlunoTemRestricoes() {
            RelaQueue queue = new RelaQueue();
            AlunoITA alunoITA = new AlunoITA("John Smith", queue);
            AlunoUSP alunoUSP = new AlunoUSP("Mark Smith", queue);
            AlunoUnicamp alunoUnicamp = new AlunoUnicamp("Joseph Smith", queue);
            try {
                alunoITA.setComportamento( new SafoPreguicoso(alunoITA) );
                alunoITA.setComportamento( new Summa(alunoITA) );
                alunoUSP.setComportamento( new Burro(alunoUSP) );
                alunoUnicamp.setComportamento( new Burro(alunoUnicamp) );
            } catch (Exception e) {
                fail("Não deveria lançar erro!");
            }
            try {
                alunoITA.setComportamento( new Burro(alunoITA) );
            } catch (Exception e) {
                //fail("Deveria lançar erro!");
                System.out.println("alunoITA não pode ser Burro");
            }
            try {
                alunoUSP.setComportamento( new SafoPreguicoso(alunoUSP) );
            } catch (Exception e) {
                //fail("Deveria lançar erro!");
                System.out.println("alunoUSP não pode ser SafoPreguicoso");
            }
            try {
                alunoUnicamp.setComportamento( new Summa(alunoUnicamp) );
            } catch (Exception e) {
                //fail("Deveria lançar erro!");
                System.out.println("alunoUSP não pode ser Summa");
            }
        }
         public void testRelaQueueEhSubclasseDoGenericoQueue() {
            Queue<Relatorio> q = new RelaQueue(); //propriedade básica do polimorfismo
        }
}
lab21.jpg
lab22.jpg

Classe Simulador

import java.util.Scanner;
import java.io.*;
public class Simulador {
    public static void main(){
        int cont;
        Aluno aluno;
        String nome;
        int tipoDeAluno;
        RelaQueue queue = new RelaQueue();
 
        BufferedReader inReader;
        inReader = new BufferedReader ( new InputStreamReader ( System.in ));
 
        System.out.println("Quantos alunos existem? ");
        Scanner scan = new Scanner (System.in);
        int numAlunos = scan.nextInt();
        aluno = new Aluno("",queue);
        for(cont=1 ; cont <= numAlunos ; cont++ ){
            try {
                System.out.print(cont+". Nome do aluno: ");
                nome = inReader.readLine();  //Ler o nome do aluno
                System.out.print("\tTipo de aluno:\n\t1.Esforcado\n\t2.SafoPreguicoso\nDigite o numero: ");
                tipoDeAluno=3;
                while ( tipoDeAluno!=1 && tipoDeAluno!=2 ) {
                    tipoDeAluno = scan.nextInt();
                    if(tipoDeAluno==1){
                        aluno = new Aluno(nome,queue);
                        try {
                            aluno.setComportamento( new Esforcado(aluno) );
                        }catch(Exception e){
                        } 
                    }
                    else if(tipoDeAluno==2){
                        aluno=new Aluno(nome,queue);
                        try {
                            aluno.setComportamento(new SafoPreguicoso(aluno));                    
                        }catch (Exception e){
                        }
                    }
                    if(tipoDeAluno!=1 && tipoDeAluno!=2)
                        System.out.print("Digite novamente: ");
                } 
            } catch (IOException e){
                System.err.println(e.getMessage());
            }
            aluno.fazEEntregaRelatorio();
        }
        if(numAlunos == 0)
            System.out.println("Não há alunos para fazer e entregar relatorio!");
        else{
            Professor prof = new Professor(queue);
            System.out.println("\n\nProfessor corrigiu os relatorio");
            System.out.println("Notas dos alunos:");
            prof.corrigirRelatorios();
        }
    }
}

Testando o Simulador

lab26.jpglab27.jpg

Arquivo com código
Todos os arquivos para BlueJ (lab2)

Conclusão

Em relaçao ao primeiro laboratório, este apresentou um nível de complexidade um pouco maior.
Houve novos conceitos aprendidos para utilizar na implementação como: lista genérica, entrada e saida de dados, tratamento de exceções.
Um ponto muito interessante desse laboratório foi observar a importância de se modelar bem as classes do aplicativo desejado, facilitando muito no caso de eventuais atualizações.
Um grande dificuldade foi na parte de genéricos, que não ficou muito claro como deveria ser feito.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License