Design mönster
Mönster
n
Visitor
n
Decorator
n
Extension Object
n
State
n
Taskmaster
Visitor
n Används för komplicerade datastrukturer där det finns en växande mängd operationer på denna
n Grafik exempel igen:
Line draw() ps()ink() svg()
Circle draw() ps()ink() svg()
Rec tangle draw() ps()ink() svg()
Group draw() ps()ink() svg() Shape
draw() ps()ink() svg()
0..*
0..*
Visitor
n
Varje ny operation kräver ändring av varje subklass
¤ Problem då ny funktionalitet ska sättas till i ett existerande system
¤ Klasser blir nertyngda med operationer
¤ Operationerna har inte nödvändigtvis mycket gemensamt
Visitor
n Introducera en visitor för varje funktion
ShapeVisitor visit(l : Line) visit(c : Circle) visit(r : Rectangle) visit(g : Group)
DrawVisitor Inkvisitor PsVisitor SvgVisitor
Visitor
n Klasshierarkin för Shapes får nu följande struktur
Line accept()
Circle accept()
Rec tangle accept()
Group accept() Shape
accept(s v : ShapeVisitor)
0..*
0..*
Visitor
n
Varje accept metod är implementerad på följande sätt:
n
Group klassen skickar dessutom besökaren vidare till sina gruppmedlemmar:
public void accept(ShapeVisitor v){
v.visit(this);
}
public void accept(ShapeVisitor v){
for ( Shape s : members) s.accept(v);
v.visit(this);
}
Visitor
n
Nu är det lätt att få operationer utförda på godtyckligt komplicerade Shape strukturer
¤ exempel: konvertering av ritning till postscript
Shape complexDrawing;
complexDrawing=//...bygge av komplex ritning ShapeVisitor ps=new ShapeVisitor();
complexDrawing.accept(ps);
Visitor
n Exempel på enkel Shape hierarki
n Anropen av metoder i objekten illustreras av följande sekvensdiagram:
ps : PsVisitor
complexDrawing : Group
: Line : Circle
Visitor
aClient
aClient ps :
ShapeVisitorps :
ShapeVisitor : Circle : Circle : Line : Line complexDrawing : Group complexDrawing :
Group 1: accept(ps)
2: acc ept(ps) 3: visit(this)
4: accept(ps) 5: visit(this)
6: visit(this)
Visitor - Sammanfattning
n
Separerar datastrukturen från operationerna på den
n
Ska endast användas då datastrukturen (Shape hierarkin) är stabil
¤ Om datastrukturen ändras är Visitor ganska meningslös
n
Visitor förhindrar att datastrukturklasserna blir fyllda av diverse orelaterade operationsuppsättningar som var och borde spridas ut i varje datastrukturklass
¤ Plugins för nya operationer
Decorator
n
Om man vill utöka beteendet hos en klass kan det ske med arv
¤ Kan inte ändras dynamiskt
¤ Vill man ge ett objekt flera nya egenskaper vid körningen fungerar inte arv
n
Bättre om objektet behåller sitt gamla gränssnitt och bara
utökas med nya egenskaper
Decorator
n
Fönster för att visa komponent
n
TextArean kanske inte får plats i fönstret – Dekorerar med rullister
Container contentPane getContentPane();
JTextArea textArea =new JTextArea(200,200);
contentPane.add(textArea);
Container contentPane getContentPane();
JTextArea textArea =new JTextArea(200,200);
JScrollPAne scrollPane=new JSCrollPane(textArea);
contentPane.add(scrollPane);
Decorator
n
Visar bara rullister när fönstret är för litet
n JScrollPane, Container och JTextArea ärver Component
¤ De ingående objektens gränssnitt bevaras
¤ Den utökade funktionaliteten är ett rent tillägg
Decorator
n Javas IO-arkitektur
n Olika streams för läsning – kan kopplas ihop på flera sätt
BufferedReader in =new BufferedReader(new FileReader(”text.txt”));
String line= in.readLine();
FileReader BufferedReader PushbackReader
Reader read() close()
Decorator generellt
ConcreteComponent
ConcreteDecorator1 addedState
addedBehaviour()
ConcreteDecorator2 Decorator
Component operation()
Decorator - sammanfattning
n
Större flexibilitet och dynamik än statiskt arv
¤ Varje kombination av dekorationer skulle behöva en egen klass
¤ Funktionalitet kan läggas till efter hand
n
En dekorator är inte identisk med originalobjektet även om den har samma gränssnitt
¤ Kan bli problem med jämförelseoperationer
¤ Man kan få många objekt att hålla reda på (jämför java.io paketet)
Extension object
n Varje objekt i en hierarki håller reda på en lista av extension objekts
¤ Mera komplicerat än decorator
¤ Men också mera flexibelt
PartExtension1<<interface>>
Part getExtension() addExtension()
PartExtension<<marker>>
PiecePartExtension1 PiecePart
AssemplyExtension1 Assemply
0..*
0..*
<<Map<String,PartExtension>>>
State
n
Implementation av ändlig tillståndsmaskin (finite state automata)
n
Erbjuder ett enkelt och elegant sätt att beskriva beteendet för komplicerade system.
n
Användbart till allt från grafiska användargränssnitt till
kommunikationsprotokoll
State
n Exempel: Parkeringsautomat
n Två händelser
¤ euro: Sätter in en euro i automaten
¤ ticket: Begär att man får en parkeringsbiljett
n Reaktionen på händelserna är olika beroende på tillstånd
idle coinInserted
euro / incSum()
euro / incSum()
ticket / giveTick et()
Tillstånds maskiner (Statemachines)
n Här består de av
n Händelser (events)
¤ Händelser från omvärlden som maskinen reagerar på
n Tillstånd (states)
¤ Reaktionen på en händelse bestäms av tillståndet som maskinen befinner sej i
n Aktioner (actions)
¤ Aktioner beskriver den effekt som en händelse har på omgivningen då maskinen är i ett visst tillstånd
State
n Informationen kan också presenteras i tabellform
idle coinInserted
idle
idle coinInserted
coinInserted
ticket euro
State - Implementation
n
Switch case
public void euro(){
switch ( state) { case IDLE:
state=COIN_INSERTED;
incSum();
break;
case COIN_INSERTED;
incSum();
break;
} }
public void ticket(){...}
State - Implementation
n
Enkelt och snabbt sätt att implememtera FSMs
¤ Fungerar bra för små tillståndsmaskiner
¤ Stora swítch-case block blir ofta oöverskådliga och svåra att hantera
¤ Dålig separation mellan logiken för tillståndsförändringar och aktioner
State - Transitionstabell
n
Kan också implementeras som tabell motsvarande tabell
representationen av tillståndsmaskinen
State - implementation
n
Enkelt att översätta från tabellrepresentation av tillståndsmaskinen
n
Lätt att underhålla jämfört med switch-case
n
Enkelt att ändra beteendet hos tillståndsmaskinen då programmet körs
n
Nackdelar:
¤ Långsam – Det tar tid att söka i tabeller
¤ En hel del kod måste skrivas för att få allt och funka
State - mönster
Idle CoinInserted
ParkingTicketDispenser state
incSum() giveTicket()
ParkingState
euro(p : ParkingTicketDispenser) ticket(p : ParkingTicketDispenser)
<<interface>>
State - implementation
n
Implementation av IDLE tillståndet
class Idle implements State{
public void euro(ParkingTicketDispenser p){
p.incSum();
p.setCoinInsertedState();
}public void ticket(){
} }
State - generellt
S1 S2 S3
Context state action1() action2()
State event1() event2() event3()
<<interface>>
State
n
Bra separering mellan aktioner och logiken för transitioner mellan tillstånd
¤ Lätt att ändra en utan att påverka den andra
n
Snabbare än tabell
¤ Antagligen lika snabbt som switch-case
¤ Bästa egenskaperna av båda tidigare lösningarna
n
Nackdelar
¤ Kräver en del arbete att skapa alla State subklasser - Många metoder gör ingenting
¤ Ingen centralt ställe att för att få överblick över logiken – svårt att underhålla
UML statemachines
s1 r1 entry/ AR1 exit/ AR2 do/ AR3
H r2
r1 entry/ AR1 exit/ AR2 do/ AR3
H r2
e2[ G2 ] / A2 ^E2 e1( p1,p2 )[ G1 ] / A1
s2
e3
e4
Taskmaster
n
Arkitektur för att hantera komplicerade sekvenser av händelser
n
Använder tillståndsmaskiner
n
Olika uppgifter (=tasks)
n
Exempel: MeasureTask
¤ Mäter avståndet mellan två punkter i ett ritprogram
¤ Användaren markerar vilka två punkter
Taskmaster
n Tillståndsmaskin beskriver interaktionen
GettingPoints Get FirstPoint
Get SecondPoint Get FirstPoint
MovePoint / Init
Get SecondPoint
GetPoint / RecordStartPt GetPoint / RecordEndPt
MouseUp
DoubleClick Cancel / ClearTask MovePoint / DragLine