Seuraavassa esitetään joukko erilaisia tapoja ratkaista annetut tehtävät. Myös muut ratkaisut ovat mahdollisia.
Tuote
Toteuta abstrakti luokka Tuote, joka esittää yksittäistä
verkkokaupan myymää tuotetta. Luokalla on seuraavat ominaisuudet:
String tunnusString kuvausLuokalla on seuraavat metodit:
Tuote(String tunnus, String kuvaus)String tunnus()String kuvaus()
Ratkaisu on muuten aivan suoraviivainen, mutta
Tuote on laitettava toteuttamaan rajapinta Comparable,
jotta tuotteiden järjestäminen toimisi osatehtävässä
2.3. Metodin compareTo(Object)
totetutus vertaa tunnus-kenttiä String-luokan
metodilla compareTo(Object).
Poikkeus ClassCastException
syntyy, jos annettu olio ei ole Tuote.
public abstract class Tuote implements Comparable {
protected String tunnus;
protected String kuvaus;
public Tuote(String tunnus, String kuvaus) {
this.tunnus = tunnus;
this.kuvaus = kuvaus;
}
public String tunnus() {
return tunnus;
}
public String kuvaus() {
return kuvaus;
}
public int compareTo(Object o) throws ClassCastException {
return tunnus().compareTo(((Tuote)o).tunnus());
}
}
Kirja
Tee Tuote-luokan alaluokka Kirja.
Luokalla on seuraavat ominaisuudet (Luokasta Tuote
perittyjen lisäksi):
String isbnString nimiSortedSet kirjoittajatLuokalla on seuraavat metodit:
Kirja(String tunnus, String nimi,
String[] kirjoittajat, String isbn)String-taulukossa. Luontimetodi muodostaa niistä
järjestetyn joukon ja tallettaa ominaisuusmuuttujaan
kirjoittajat. Tuotteen kuvausta ei anneta
parametrina, vaan se muodostetaan luontimetodissa kirjan ja
kirjoittajien nimistä sekä ISBN-numerosta.
String isbn()String nimi()SortedSet kirjoittajat()String toString()
Tässä ainoa suurempi ongelma on tuotekuvauksen muodostaminen
yläluokan Tuote luontimetodia
varten. Kirja-luokan luontimetodi saa parametrinaan
kirjan nimen, taulukon kirjoittajien nimiä ja isbn:n. Näistä
pitäisi muodostaa järjellinen kirjan kuvaus, joka annetaan
super-kutsulle parametrina.
Seuraavassa ongelma on ratkaistu ottamalla käyttöön protected
määreellä varustettu sisäinen luontimetodi, joka ottaa parametrinaan
kirjoittajien nimiä sisältävän taulukon tilalta SortedSet-tyyppisen kokoelman, jossa kirjoittajat ovat aakkosjärjestyksessä.
Varsinainen luontimetodi kutsuu sisäistä luontimetodia.
Sisäinen luontimetodi kutsuu apumetodia
siistiKirjoittajat, joka muodostaa
kirjoittajakokoelmasta siistin merkkijonon. Tämä merkkijono
yhdistetään muihin parametreihin ja välitetään luokan
Tuote luontimetodille super-kutsussa.
Myös muunlaiset ratkaisut ovat mahdollisia. Tässä sisäistä luontimetodia on käytetty myös esimerkin vuoksi.
import java.util.Arrays;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
public class Kirja extends Tuote {
protected String nimi;
protected SortedSet kirjoittajat;
protected String isbn;
// Apumetodi
protected static String siistiKirjoittajat(SortedSet kirjoittajat) {
String tulos = "";
Iterator it = kirjoittajat.iterator();
while (it.hasNext()) {
String nimi = (String)it.next();
tulos = tulos + nimi;
if (it.hasNext()) {
tulos = tulos + ", ";
}
}
return tulos;
}
// Sisäinen luontimetodi
protected Kirja(String tunnus, String nimi, SortedSet kirjoittajat,
String isbn) {
super(tunnus, siistiKirjoittajat(kirjoittajat)
+ ": " + nimi
+ ". ISBN: " + isbn);
this.nimi = nimi;
this.kirjoittajat = kirjoittajat;
this.isbn = isbn;
}
public Kirja(String tunnus, String nimi, String[] kirjoittajat, String isbn) {
this(tunnus, nimi, new TreeSet(Arrays.asList(kirjoittajat)), isbn);
}
public String isbn() {
return isbn;
}
public String nimi() {
return nimi;
}
public SortedSet kirjoittajat() {
return kirjoittajat;
}
public String toString() {
return "Kirja[" + tunnus() + ", " + nimi() + "]";
}
}
CD
Tee Tuote-luokan alaluokka CD.
Sillä on Tuote-luokassa määriteltyjen attribuuttien
lisäksi seuraavat ominaisuudet:
String nimiString esittäjäLuokalla on seuraavat metodit:
CD(String tunnus, String nimi,
String esittäjä)
String nimi()String esittäjä()String toString()Tämä on suoraviivaista koodia.
public class CD extends Tuote {
protected String nimi;
protected String esittäjä;
public CD(String tunnus, String nimi, String esittäjä) {
super(tunnus, esittäjä + ": " + nimi);
this.nimi = nimi;
this.esittäjä = esittäjä;
}
public String nimi() {
return nimi;
}
public String esittäjä() {
return esittäjä;
}
public String toString() {
return "CD[" + tunnus() + ", " + nimi() + "]";
}
}
Valikoima
Kirjoita luokka Valikoima, joka sisältää
verkkokaupan tarjoamat tuotteet, jotka ovat siis kirjoja ja
CD:itä. Luokalla on seuraavat ominaisuudet:
Map tuotteetLuokalla on seuraavat metodit:
Valikoima()void lisääTuote(Tuote uusi)void poistaTuote(Tuote tuote)Collection tuoteKokoelma()Collection kirjaKokoelma()Collection CDKokoelma()Tuote haeTuote(String tunnus)tunnus. Jos
sitä ei löydy, palauttaa arvon null.
Set haeTuotteet(String s)s. Palauttaa tuloksen joukkona.
Merkkijonon s etsiminen kuvauksesta tapahtuu
String-luokan metodilla indexOf.
String toString()
Ratkaisu on pääosin suoraviivainen. Rajapinnan java.util.Map
toteutukseksi on valittu luokka java.util.HashMap.
Metodit kirjaKokoelma ja CDKokoelma ja
toteutetaan käymällä iteraattorilla läpi kaikki
tuoteKokoelma-metodin palauttamat tuotteet ja
poimimalla niistä oikean tyyppiset uuteen kokoelmaan. Syntynyt
kokoelma palautetaan. Metodi haeTuotteet käy läpi
kaikki tuotteet ja etsii
luokan String metodilla indexOf(String) kaikki tuotteet, joiden kuvaus sisältää etsityn merkkijonon.
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class Valikoima {
protected Map tuotteet;
public Valikoima() {
tuotteet = new HashMap();
}
public void lisääTuote(Tuote t) {
tuotteet.put(t.tunnus(), t);
}
public void poistaTuote(Tuote t) {
tuotteet.remove(t.tunnus());
}
public Collection tuoteKokoelma() {
return tuotteet.values();
}
public Collection kirjaKokoelma() {
Collection result = new LinkedList();
Iterator it = tuoteKokoelma().iterator();
while (it.hasNext()) {
Tuote t = (Tuote)it.next();
if (t instanceof Kirja) {
result.add(t);
}
}
return result;
}
public Collection CDKokoelma() {
Collection result = new LinkedList();
Iterator it = tuoteKokoelma().iterator();
while (it.hasNext()) {
Tuote t = (Tuote)it.next();
if (t instanceof CD) {
result.add(t);
}
}
return result;
}
public Tuote haeTuote(String tunnus) {
return (Tuote)tuotteet.get(tunnus);
}
public Set haeTuotteet(String s) {
Set result = new HashSet();
Iterator it = tuoteKokoelma().iterator();
while (it.hasNext()) {
Tuote t = (Tuote)it.next();
if (t.kuvaus().indexOf(s) >= 0) {
result.add(t);
}
}
return result;
}
public String toString() {
return "Valikoima[" + kirjaKokoelma().size() + " kirjaa, "
+ CDKokoelma().size() + " CD:tä]";
}
}
Ostoskori
Tee luokka Ostoskori, joka sisältää asiakkaan
valitsemat tuotteet. Luokalla on seuraavat ominaisuudet:
String asiakasList ostoksetLuokalla on seuraavat metodit:
Ostoskori(String asiakas)String asiakas()void lisääTuote(Tuote uusi)void poistaTuote(Tuote tuote)List tuotteetString toString()
Ratkaisu on suoraviivainen. Rajapinnan java.util.List
toteutukseksi on valittu luokka java.util.LinkedList. Metodissa
tuotteet ostokset järjestetään luokan java.util.Collections
metodilla sort(List).
Tämä onnistuu, koska Tuote-luokkka toteuttaa
rajapinnan Comparable.
import java.util.Collections;
import java.util.List;
import java.util.LinkedList;
public class Ostoskori {
protected String asiakas;
protected List ostokset;
public Ostoskori(String asiakas) {
this.asiakas = asiakas;
ostokset = new LinkedList();
}
public String asiakas() {
return asiakas;
}
public void lisääTuote(Tuote uusi) {
ostokset.add(uusi);
}
public void poistaTuote(Tuote uusi) {
ostokset.remove(uusi);
}
public List tuotteet() {
Collections.sort(ostokset);
return ostokset;
}
public String toString() {
return "Ostoskori[" + asiakas() + " , " + ostokset.size() + " tuotetta]";
}
}
VerkkokauppaLaadi pääohjelmaluokka, jolla voit testata verkkokauppaa.
Oheisessa pääohjelmassa luodaan Valikoima ja lisätään sinne
kirjoja ja CD:itä. Sitten luodaan Ostoskori ja
lisätään sinne tuotteita. Osa tuotteista lisätään useita kertoja.
Lopuksi ostoskorin sisältö tulostetaan.
import java.util.Iterator;
public class Verkkokauppa {
public static void main(String[] args) {
Valikoima v = new Valikoima();
v.lisääTuote(new Kirja("0001",
"The Java Language Specification Second Edition",
new String[]{"Gosling, James", "Joy, Bill",
"Steele, Guy", "Bracha, Gilad"},
"0-201-31008-2"));
v.lisääTuote(new CD("0020", "Hard Rock Cafe", "The Doors"));
v.lisääTuote(new CD("0037", "Wired", "Jeff Beck"));
v.lisääTuote(new CD("0127", "Humppakäräjät", "Eläkeläiset"));
v.lisääTuote(new Kirja("0005",
"Change. Principles of Problem Formation and Problem Resolution",
new String[]{"Watzlawick, Paul",
"Weakland, John",
"Fisch, Richard"},
"0-393-01104-6"));
v.lisääTuote(new CD("0120", "Pancha Nadai Pallavi", "Shankar"));
v.lisääTuote(new Kirja("0011",
"Women, Fire, and Dangerous Things: What Categories Reveal About the Mind",
new String[]{"Lakoff, George"},
"0-226-46804-6"));
System.out.println(v);
Ostoskori o = new Ostoskori("Arska Asiakas");
System.out.println(o);
o.lisääTuote(v.haeTuote("0120"));
o.lisääTuote(v.haeTuote("0011"));
o.lisääTuote(v.haeTuote("0011"));
o.lisääTuote(v.haeTuote("0127"));
o.lisääTuote(v.haeTuote("0127"));
o.lisääTuote(v.haeTuote("0037"));
o.lisääTuote(v.haeTuote("0005"));
System.out.println(o + ": ");
Iterator it = o.tuotteet().iterator();
while (it.hasNext()) {
Tuote t = (Tuote)it.next();
System.out.println(t.kuvaus());
}
}
}
Valikoima[3 kirjaa, 4 CD:tä]
Ostoskori[Arska Asiakas , 0 tuotetta]
Ostoskori[Arska Asiakas , 7 tuotetta]:
Fisch, Richard, Watzlawick, Paul, Weakland, John: Change. Principles of Problem Formation and Problem Resolution. ISBN: 0-393-01104-6
Lakoff, George: Women, Fire, and Dangerous Things: What Categories Reveal About the Mind. ISBN: 0-226-46804-6
Lakoff, George: Women, Fire, and Dangerous Things: What Categories Reveal About the Mind. ISBN: 0-226-46804-6
Jeff Beck: Wired
Shankar: Pancha Nadai Pallavi
Eläkeläiset: Humppakäräjät
Eläkeläiset: Humppakäräjät