Dette eksemplet er ment å illustrere to ting:
- Hvordan oppgavene til et komplekst objekt kan deles opp og fordeles over flere objekter.
- 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: |
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. 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. Hver av disse
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(); } } | 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++; } }
|