You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 11 Next »

RandomMinMaksSnitt-eksemplet er et kode-eksempel som viser bruk av hovedprogram for å bruke/teste flere andre (små)klasser.

Dette eksemplet er ment å illustrere to ting:

  1. Hvordan oppgavene til et komplekst objekt kan deles opp og fordeles over flere objekter.
  2. Hvordan et hovedprogram, kodet i en hovedprogramklasse, kan brukes for å koordinere og prøve ut andre klasser.

Anta at du skal prøve ut en metode for å lage tilfeldige tall, f.eks. basert på http://en.wikipedia.org/wiki/Random_number_generation. I første omgang ønsker du å lage 1000 tilfeldige tall og sjekke minimum-, maksimum og gjennomsnittsverdien. Her er en hovedprogramklasse som inneholder algoritmen fra Wikipedia og som beregner de tre nevnte verdiene.

// fra http://en.wikipedia.org/wiki/Random_number_generation
public class RandomProgram1 {

    // tilstand for tilfeldig tall-generatoren
    long mw = 31;
    long mz = 42;
     
    long nextRandom() {
        mz = 36969 * (mz & 65535) + (mz >> 16);
        mw = 18000 * (mw & 65535) + (mw >> 16);
        return (mz << 16) + mw;
    }

	void init() {
    }
    
    // tilstand for minimum
    long min = Long.MAX_VALUE;
    // tilstand for maksimum
    long max = Long.MIN_VALUE;
    // tilstand for gjennomsnitt
    int count = 0;
    long sum = 0;
    
    void run() {
        while (count < 1000) {
            long randomValue = nextRandom();
            if (randomValue < min) {
                min = randomValue;
            }
            if (randomValue > max) {
                max = randomValue;
            }
            sum += randomValue;
            count++;
        }
        System.out.println("Min: " + min);
        System.out.println("Max: " + max);
        System.out.println("Average: " + (sum / count));
    }
    
    public static void main(String[] args) {
        RandomProgram1 program = new RandomProgram1();
        program.init();
        program.run();
    }
}

De to første long-attributtene m_w og m_z er tilstand knyttet til tilfeldige tall-generatoren. For hvert nye tilfeldige tall som beregnes av nextRandom()-metoden, så oppdateres disse to attributtene.

min- og max-attributtene holder henholdsvis hittil minste og hittil største verdi, og initialiseres til henholdsvis den største og minste mulige long-verdiene i Java.

count- og sum-attributtene brukes for å beregne gjennomsnittet.

init()-metoden er tom, siden den gjerne brukes til å konfigurere objekt(struktur)er og vi her ikke har noen objekter (bortsett fra hovedprogram-objektet).

run()-metoden inneholder en løkke som går 1000 ganger. For hver runde så lager den et nytt tilfeldig tall med nextRandom()-metoden og oppdaterer min-, max-, sum- og count-attributtene. min oppdateres hvis den nye verdien er mindre, max oppdateres hvis den nye verdien er større og sum og count oppdateres alltid.

Et objekttilstandsdiagram for klassen vil se slik ut:

RandomProgram1// tilstand for generatormw = 31mz = 42// tilstand for minimummin = 9223372036854775807// tilstand for maksimummax = -9223372036854775808// tilstand for gjennomsnittcount = 0sum = 0RandomProgram1// tilstand for generatormw = 558000mz = 1552698// tilstand for minimummin = 101758174128// tilstand for maksimummax = 101758174128// tilstand for gjennomsnittcount = 1sum = 101758174128RandomProgram1// tilstand for generatormw = 606816008mz = 1677283553// tilstand for minimummin = 101758174128// tilstand for maksimummax = 109923061745416 // tilstand for gjennomsnittcount = 2sum = 110024819919544RandomProgram1// tilstand for generatormw = 290483840mz = 1240974898// tilstand for minimummin = 3057780577// tilstand for maksimummax = 158694648374228// tilstand for gjennomsnittcount = 1000sum = 78963637600257262runde 1runde 2... runde 1000

Ulempene med denne klassen er flere, bl.a.

  • Klassen har mange oppgaver å utføre og attributter å holde rede på.
  • Det er vanskelig å holde rede på hvilke attributter som brukes til hvilket formål.
  • count-attributter brukes til to formål: å holde rede på antall runder i løkka og hjelpe til å beregne gjennomsnitt
  • Dersom en vil undersøke andre egenskaper til tilfeldig tall-generatoren så blir det mer og mer forvirrende

En ryddigere løsning er å dele problemet opp i mindre deler og la én klasse ta seg av hver del. Dette er grunnprinsippet i objektorientering: En klasse skal ha (kun) ett formål! Her er det naturlig å ha én klasse for tilfeldig tall-generatoren, én for å holde rede på minimumsverdien, én for å holde rede på maksimumsverdien og én for å håndtere gjennomsnittberegningen. Siden hver av disse kun har ett formål og gjør én ting, så er det enkle å skrive.

public class RandomProgram2 {
    Random random;
    Min min;
    Max max;
    Average average;
    
    void init() {
        random = new Random();
        min = new Min();
        max = new Max();
        average = new Average();
    }
    
    void run() {
        for (int i = 0; i < 1000; i++) {
            long randomValue = random.nextRandom();
            min.accumulate(randomValue);
            max.accumulate(randomValue);
            average.accumulate(randomValue);
        }
        System.out.println("Min: " + min.getMin());
        System.out.println("Max: " + max.getMax());
        System.out.println("Average: " + average.getAverage());
    }
    
    public static void main(String[] args) {
        RandomProgram2 program = new RandomProgram2();
        program.init();
        program.run();
    }
}
RandomProgram2Randommw = 31mz = 42Minmin = 9223372036854775807Maxmax = -9223372036854775808Averagecount = 0sum = 0RandomProgram2Randommw = 558000mz = 1552698Minmin = 101758174128Maxmax = 101758174128Averagecount = 1sum = 101758174128RandomProgram2Randommw = 606816008mz = 1677283553Minmin = 101758174128Maxmax = 109923061745416Averagecount = 2sum = 110024819919544RandomProgram1Randommw = 290483840mz = 1240974898Minmin = 3057780577Maxmax = 158694648374228Averagecount = 1000sum = 78963637600257262randomminmaxaveragerandomminmaxaveragerunde 1randomminmaxaveragerunde 2randomminmaxaverage... runde 1000
public class Random {

    // from http://en.wikipedia.org/wiki/Random_number_generation

    long mw = 31;
    long mz = 42;
     
    long nextRandom() {
        mz = 36969 * (mz & 65535) + (mz >> 16);
        mw = 18000 * (mw & 65535) + (mw >> 16);
        return (mz << 16) + mw;
    }
}
public class Min {
    long min = Long.MAX_VALUE;
    
    public long getMin() {
        return min;
    }
    
    void accumulate(long value) {
        if (value < min) {
            min = value;
        }
    }
}
public class Max {
    long max = Long.MIN_VALUE;
    
    public long getMax() {
        return max;
    }
    
    void accumulate(long value) {
        if (value > max) {
            max = value;
        }
    }
}
public class Average {
    long count = 0, sum = 0;
    
    long getAverage() {
        return sum / count;
    }
    
    void accumulate(long value) {
        sum += value;
        count++;
    }
}

 

 

 

 

 

  • No labels