Observatør-observert-teknikken går ut på at det observerte objektet sier ifra til en eller flere observatører om at tilstanden er endret. I denne oppgaven skal vi lage en HighscoreList som kan si fra til lyttere av typen ListListener når nye resultater blir registrert. En hovedprogramklasse kalt HighscoreProgram vil bli brukt til å sjekke at det virker. Denne klassen oppretter en HighscoreList-instans, legger inn resultater (tall) fra konsollet som legges til lista og skriver ut lista hver gang et nytt resultat faktisk blir lagt til.
Del 1: Implementasjon av ObservableList og ObservableHighscoreList
Klassediagram for HighscoreList, ListListener og ObservableList. | En ObservableHighscoreList skal holde styr på heltallsresultater (av typen int/Integer). Lista skal være observerbar ved at den kan registrere lyttere (ObservableListListener-instanser) og si fra til dem når lista blir endret. Lista skal ha en maksimal lengde, som settes i konstruktøren, f.eks. skal en topp 10-liste kunne opprettes med new ObservableHighscoreList(10). Nye resultater registreres med metoden addResult(int), som skal finne riktig posisjon og legge resultatet inn (dersom det er godt nok). Dersom lista er for lang, så skal det dårligste resultatet fjernes. NB: Lavest verdi er best, f.eks. antall sekunder på en oppgave eller antall flytt i Sokoban. ObservableListListener-grensesnittet er vist i klassediagrammet til venstre og må implementers av alle klasser som ønsker å fungere som lyttere for ObservableHighscoreList-instanser. Lyttere registrerer seg med ObservableHighscoreList sin addObservableListListener-metode og vil siden få beskjed om nye resultater ved at listChanged-metoden kalles. Argumentene som tas inn er ObservableHighscoreList-objektet som ble endret og posisjonen i lista der endringen skjedde. Merk at første argument til listChanged-metoden er av typen ObservableList. Dette er en abstrakt superklasse for ObservableHighscoreList, som først brukes i del 3 og som da skal holde orden på lista. ObservableList vil ha en del generelle metoder som ObservableHighscoreList arver og kan bruke. For å kunne kjøre testene for ObservableHighscoreList allerede i del 1, så må ObservableList være definert fra starten. Lag derfor en tom ObservableList-klasse og bruk denne som superklasse for ObservableHighscoreList. Her er en oversikt over metoden som må implementeres:
|
Testkode for denne oppgaven finner du her: patterns/observable/ObservableHighscoreListTest.java. Original-koden (jextest) finner du her: patterns/observable/ObservableHighscoreList.jextest.
Del 2: Hovedprogram ObservableHighscoreListProgram
Klassediagrammet viser hvordan klassene henger sammen, og vårt forslag til metoder. | Lag en hovedprogramklasse kalt ObservableHighscoreListProgram, som tester at ObservableHighscoreList-klassen din virker som den skal. La den opprette en ObservableHighscoreList-instans, lese inn tall fra konsollet (f.eks. med en Scanner og nextInt-metoden) og legge disse inn i lista. Sørg for at ObservableHighscoreListProgram implementerer ObservableListListener-grensesnittet og registrerer seg som lytter på HighscoreList-instansen. La lyttermetoden listChanged skrive ut informasjon og resultatene i HighscoreList-instansen og posisjonsargumentet, slik at du ser at alt virker som det skal. Vi foreslår følgende metoder og oppførsel:
|
Del 3: ObservableList
Klassediagrammet viser hvordan klassene henger sammen, og hvor metodene nå er deklarert/implementert. Merk at addElement- og removeElement-metodene er angitt som protected (ruter-symbolet), slik at kun subklasser skal kunne bruke dem. | Den abstrakte superklassen ObservableList skal legges til som en generell superklasse for observerbare lister, som ObservableHighscoreList skal arve fra. Denne klassen skal både holde en liste med objekter (Object) og håndtere registrering av lyttere, altså en liste med ObservableListListener-instanse, som får beskjed om endringer i lista (slik at lista dermed er observerbar). Dette betyr at ObservableList overtar håndtering av både resultater og lyttere fra ObservableHighscoreList-klassen. For å gjøre ObservableList mer generell og gjenbrukbar, så lar vi den håndtere Object-instanser (heller enn Integer). Samtidig deklarerer den en abstrakt metode acceptsElement, som subklasser må redefinere for å bestemme hva slags objekter det skal være lov å legge inn. ObservableHighscoreList vil f.eks måtte redefinere den slik at bare Integer-objekter aksepteres. ObservableList skal ha følgende metoder (noen er altså overtatt fra ObservableHighscoreList):
ObservableHighscoreList skal endres slik at den i størst mulig grad bruker metodene som arves fra ObservableList, men forøvrig ikke endrer oppførsel. Kjør hovedprogramklassen ObservableHighscoreListProgram for å sjekke at dette faktisk stemmer.
|
Testkode for denne oppgaven finner du her: patterns/observable/ObservableListTest.java. Original-koden (jextest) finner du her: patterns/observable/ObservableList.jextest.
.ex for bruk med Exercise-panelet finner du her: ObservableListInheritance.ex.
Ekstraoppgave
Implementer en ObservableHighscoreList som håndterer resultater for TicTacToe, Sokoban eller Sudoku. Etter hvert ferdige spill skal spilleren få mulighet til å legge inn resultatene i en highscore-liste, som består av navn på spilleren og antall trekk. Hvert resultat lagres som et eget objekt, og denne resultatobjektklassen må implementere Comparable-grensesnitt. Resultatene legges inn i highscore-listen, som printes etter at spilleren har fått mulighet til å registrere sitt resultat.
JExercise lar deg sjekke din egen kode vha. forhåndslagde JUnit-tester og JExercise-panelet.
Bruk av JExercise:
- Sørg for at jexercise-standalone.jar er lagt til i ditt prosjekts Build Path. Dette må gjøres hver gang du oppretter et nytt prosjekt, og det er derfor lurt å gjenbruke samme prosjekt til alle oppgaver.
- JExercise-tillegget må være installert. Installer tillegget fra følgende oppdateringsadresse: http://folk.ntnu.no/hal/dev/updatesite.
- Åpne JExercise-panelet via Window -> Show View -> Other, og navigere deg fram til JExercise i vinduet som kommer opp, velge det og klikke OK.
- Klikke og dra oppgavens testklasse, <oppgavenavn>Test.java fra pakkeoversikten og slippe den i JExercise panelet.
- Testene kan så kjøres ved å dobbeltklikke på testen som ønskes kjørt.
Ved trøbbel, se først om du finner løsningen i Løsninger på trøbbel med JExercise.
Twitre gjerne om oppgaven når du er ferdig: <a href="https://twitter.com/share" class="twitter-share-button" data-hashtags="jexercise">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>