Institutionen för Datavetenskap Göteborgs universitet HT2009 DIT011 Objektorienterad programvaruutveckling GU (DIT011) Innehåll Föreläsning 8 Två designmönster, MVC och Observer/Observable. Designrekommendation för klasser. Efter rast kommer Joachim von Hacht och presenterar fortsättningskursen Föreläsning 8 Katarina Blom 1 2 MVC Allmän princip: Klasser ska vara löst kopplade. MVC: Modellen känner inte till vyn eller kontrollen (kontrollen och vyn känner till modellen). Vy Modell Kontroll Exempel MVC import java.awt.color; public class Modellen{ private Color färg; public void setstarttillstånd(){ public Color avlästillstånd(){ return färg; public void uppdateratillstånd(){ if(färg.equals(color.blue)) else färg = Color.blue; 3 4
Exempel (forts) MVC import java.awt.*; import java.util.*; public class Vy extends JPanel{ private Modellen mod; public Vy(Modellen m){ mod = m; setpreferredsize(new Dimension(50,50)); public void paintcomponent(graphics g){ super.paintcomponent(g); Color f = mod.avlästillstånd(); setbackground(f); Exempel (forts) MVC import java.awt.event.*; public class Kontroll extends JButton implements ActionListener{ private Modellen mod; private Vy vy; public Kontroll(Modellen m, Vy v){ mod = m; vy = v; addactionlistener(this); public void actionperformed(actionevent e) { mod.uppdateratillstånd(); vy.repaint(); 5 6 Exempel (forts) MVC import java.awt.*; public class Main{ public static void main(string[] args){ Modellen mod = new Modellen(); mod.setstarttillstånd(); Vy vy = new Vy(mod); Kontroll kontr = new Kontroll(mod,vy); JFrame f = new JFrame(); f.add(vy,"north"); f.add(kontr,"south"); f.pack(); f.setvisible(true); f.setdefaultcloseoperation(jframe.exit_on_close); (Överkurs) Men kanske bara modellen vet om vyn behöver uppdateras? Designmönstret Observer/Observable stöds av Java. Vy Observatör Modell Observerad Kontroll 7 8
(Överkurs) Vy-klassen i Observer/Observable Låt vyn vara observatör av modellen. Vyn registrerar sig som observatör genom att implementera interfacet java.util.observer, och anmäla sig som observatör till modellen. interface java.util.observer{ void update(observable o, Object arg); (Överkurs) Vy som observatör import javax.swing.jpanel; import java.awt.*; import java.util.*; public class Vy extends JPanel implements Observer{ Modellen mod; public Vy(Modellen m){ mod = m; setpreferredsize(new Dimension(50,50)); mod.addobserver(this); public void paintcomponent(graphics g){ super.paintcomponent(g); Color f = mod.avlästillståndet(); setbackground(f); public void update(observable o, Object arg){ repaint(); 9 10 (Överkurs) Modellen observeras Modellen skrivs som subklass till java.util.observable och kan därmed bli observerad: public class Observable{ public void addobserver(observer o){... public void setchanged(){... public void notifyobservers(object arg){... (Överkurs) Modellen import java.util.observable; import java.awt.color; public class Modellen extends Observable{ private Color färg; public void setstarttillstånd(){ setchanged(); notifyobservers(); public Color avlästillståndet(){ return färg; public void uppdateramodellen(){ if(färg.equals(color.blue)) else färg = Color.blue; setchanged(); notifyobservers(); När tillståndet ändrats uppdateras objekten som observerar 11 12
(Överkurs) Kontroll uppdaterar bara modellen import java.awt.event.*; public class Kontroll extends JButton implements ActionListener{ private Modellen mod; private Vy vy; public Kontroll(Modellen m){ mod = m; addactionlistener(this); Designmönster Ett sätt att utforma program är att lära sig från beprövade mönster för lösning av återkommande problem. Vi har nu sett två designmönster: MVC-arkitekturen Observer/Observable public void actionperformed(actionevent e) { mod.uppdateratillstånd(); 13 14 Det finns design-rekomendationer för hur man utformar en klass För publika klasser (som designas för en allmän användning) kan man följa nedastående rekommendation: Klassen bör ha en parameterlös konstruktor. De ärvda metoderna equals och hashcode bör omdefineras. Metoderna ärvs från Object. Det bör finnas en tostring metod. Klassen bör implementera interfacet Clonable. Klassen bör implementera interfacet Serializable. Obs, det finns många rekommendationer, detta är en 15 Parameterlös konstruktor Allmänt: Om man i en klass inte definierar någon konstruktor får man automatiskt en utan parametrar som inte gör någonting. Om man definierar minst en konstruktor får man inte någon parameterfri variant automatiskt. I konstruktorn för en subklass läggs ett anrop av superklassens parameterfria konstruktor till (ifall man inte har gjort ett anrop till någon annan konstruktor). java-systemet utgår från att det finns en parameterlös konstruktor. 16
Metoden equals() i klassen Object equals() finns definierad i Object (och ärvs alltså av alla andra klasser) o1.equals(o2) returnerar true oom o1 och o2 refererar till samma objekt. De flesta inbyggda klasser definierar därför sin egen equals()-metod. Att omdefinera equals()-metoden (Obs Överkurs) Följande kontrakt bör följas: Reflexivitet: x.equals(x) == true Symmetri: x.equals(y) == true <=> y.equals(x) == true Transivitet: (x.equals(y) == true och y.equals(z) == true ) => x.equals(z) == true Konsistens: Om tillstånden påxochyinte förändras ska anropet x.equals(y) alltid ge samma svar. Icke null: x.equals(null) är alltid false 17 18 Metoden hashcode() hashcode() finns definerad i Object (och ärvs alltså av alla andra klasser). hashcode() används av klasser som implementerar Hashtabeller (tex HashMap och Om man omdefinerar equals() bör man omdefinera hashcode(). Om x.equals(y) == true så ska x.hashcode() == y.hashcode() Att klona objekt (Överkurs) Metoden clone() returnerar en kopia av objektet. clone() finns definerad i klassen Object. Om en klass implementerar Cloneable då returnerar metoden clone() en Shallow copy av objekt av klassen. Om klassen inte implementerar Cloneable kastar metoden clone() ett CloneNotSupportedException Det gäller att (kontraktet för clone()): o.clone()!=o o och o.clone() måste vara instanser av samma klass. (o.clone()).equals(o) 19 20
Metoden tostring() Metoden tostring() finns definerad i klassen Object De flesta klasser omdefinierar tostring() Det finns metoder i standardklasser (tex println() som anropar klassens tostring()-metod Serialisering (Överkurs) Att transformera ett objekt till en byteström kallas serialisering. Serialiserade objekt kan sparas på filer, skickas iväg över näteverk. Klasser som implementerar Serializable kan serialiseras. Interfacet har inga metoder. Det räcker att bara skriva implements Serializable så implementeras interfacet. 21 22