Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

PlantUML Macro
class ObservableList {
}

class HighscoreList {
	int maxSize
	Collection<Integer> results
	HighscoreList(int)
	int size()
	int getElement(int)
	void addResult(int)
	addListListener(ListListener)
	removeListListener(ListListener)
}

ObservableList <|-- HighscoreList

interface ListListener {
	listChanged(ObservableList, int)
}
ObservableList -right-> "*" ListListener: listListeners

class HighscoreProgram {
	HighscoreList highscoreList
	void init()
	void run()
}
ListListener <|.. HighscoreProgram

Lag en hovedprogramklasse kalt HighscoreProgram, som tester at HighscoreList-klassen din virker som den skal. La den opprette en HighscoreList-instans, lese inn tall fra konsollet (f.eks. med en Scanner og nextInt-metoden) og legge disse inn i lista. Sørg for at HighscoreProgram implementerer ListListener-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:

  • void init() - oppretter en ny HighscoreList og registrerer seg selv (altså HighscoreProgram-instansen) som lytter
  • void run() - leser inn tall (resultater) fra konsollet og legger dem til i listen
  • void listChanged(ObservableList, int) - observerer endringer i HighscoreList-instansen og skriver ut posisjonsargumentet, samt selve listen, til konsollet

Klassediagrammet til venstre viser hvordan klassene henger sammen, og vårt forslag til metoder.

Del 3:

...

ObservableList

PlantUML Macro
class ObservableList {
	Collection<Object> elements
	int size()
	Object getElement(int)
	{abstract} boolean acceptsElement(Object)
	#addElement(int, Object)
	#addElement(Object)
	#removeElement(int)
 	addListListener(ListListener)
	removeListListener(ListListener)
}

class HighscoreList {
	int maxSize
	HighscoreList(int)
	boolean acceptsElement(Object)
	void addResult(int)
}

ObservableList <|-- HighscoreList

interface ListListener {
	listChanged(ObservableList, int)
}
ObservableList -right-> "*" ListListener: listListeners

Den abstrakte superklassen ObservableList skal legges til som en generell superklasse for observerbare lister, som HighscoreList skal arve fra. Denne klassen skal både holde

...

AbstractObservableList har i tillegg metoder for å legge og fjerne elementer i den observerbare listen:

...

en liste med objekter (Object) og håndtere registrering av lyttere, altså en liste med ListListener-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 HighscoreList-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. HighscoreList vil f.eks måtte redefinere den slik at bare Integer-objekter aksepteres.

ObservableList skal ha følgende metoder (noen er altså overtatt fra HighscoreList):

  • int size() - returnerer antall elementer i lista
  • Object getElement(int) - returnerer elementet i posisjonen angitt av argumentet

...

  • abstract boolean acceptsElement(Object) - returnerer hvorvidt subklassen aksepterer

...

  • at objektet legges inn i lista (f.eks. aksepterer HighscoreList kun

...

  • Integer-objekter).

...

  • void addElement(int, Object-

...

  • legger til et element på posisjonen angitt av argumentet, men bare dersom det aksepteres som element. Dersom elementet ikke aksepteres, så skal IllegalArgumentException utløses. Dersom posisjonen er ulovlig så skal IndexOutOfBoundsException utløses.
  • void addElement(

...

  • Object) - legger til et element

...

  • bakerst i lista, men bare dersom det aksepteres som element. Dersom elementet ikke aksepteres, så skal IllegalArgumentException utløses.
  • void removeElement(int) - fjerner

...

  • elementet på posisjonen angitt av argumentet

...

  • . Dersom posisjonen er ulovlig så skal IndexOutOfBoundsException utløses.

HighscoreList skal endres slik at den i størst mulig grad bruker metodene som arves fra ObservableList, men forøvrig ikke endre oppførsel.

Klassediagrammet til venstre 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.

 

JExercise-testkode for denne oppgaven finner du her: patterns/observable/ObservableListTest.java. Original-koden (jextest) finner du her: patterns/observable/ObservableList.jextestHusk at metodene bør være innkapslet så stramt som mulig.

Ekstraoppgave

Implementer en HighscoreList 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. Resultatobjektet legges inn i highscore-listen, som printes etter at spilleren har fått mulighet til å registrere sitt resultat.

...