1 / 30

Design Patterns

Design Patterns. Introductie Verschillende design patterns. Een kataloog van 23 patronen. Een klasieker in software engineering, behoort tot de vaste vocabulaire van software ontwikkelaar. “Gang of Four” (GOF), 1995. Design Pattern.

alena
Download Presentation

Design Patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Design Patterns Introductie Verschillende design patterns

  2. Een kataloog van 23 patronen. • Een klasieker in software engineering, behoort tot de vaste vocabulaire van software ontwikkelaar “Gang of Four” (GOF), 1995

  3. Design Pattern • Een generieke en praktijk-bewezen oplossing van een probleem. • Ook nuttig als vocabulaire. • Elk programma is toch generiek?Ok, maar kan het niet generieker zijn? naarBools :: [Int]  [Bool] naarBools [ ] = [ ] naarBools (x:s) = (x==0) : naarBoolss

  4. Generieke oplossing.. • In FPGeneriek in: • waarde van de inputlijst • types van de elementen van de input- en outputlijsten • bewerkingelement (de f ) • Sleutel instrumenten: polymorfisme, hogere orde functie • Nog generieker ?  ik wil ook een map over een boom… map :: (a  b)  [a]  [b] map f [ ] = [ ] map f (x:s) = f x : map fs

  5. Parameters… • Sleutel instrument: je maakt een oplossing generiek door het te parametriseren…Je instantiërt de oplossing door de parameters te instantiëren. • Door je de beperkingen van je taal, kun je niet alle aspecten laten parametriseren. map :: (a  b)  [a]  [b] map f [ ] = [ ] map f (x:s) = f x : map fs

  6. In OO wereld… • Je heb generieke oplossingen nodig! • Je hebt generics, maar geen echte hogere orde functies. • Design patterns zijn meestal in UML klassediagramen uitgedrukt • heeft geen concept van parameters! • ik zal proberen om aan te geven, maar hoe dan ook impliciet… • Betere alternatief dan klassediagram? • Klasse en relatie hebben rijker structuur dan een functie (attributen, methoden, toegangsmodifiers, static elementen) … dus hoe dan ook ingewikkeld.

  7. Voorbeeld • Parametriseerbaar in C • Staat bekend als de Singleton Pattern. Probleem 1: Ik wil dat een klasse C slechts 1x object heeft. • C • C() • $ x = new C() • +$ getInstantie() : C getInstantie() { return x ; } PS: deze oplossing is niet lazy. Stel de creatie uit tot het gevraagd wordt  kijk uit voor race conditie in concurrent setup

  8. Overzicht • Creatorpatronen: • Singleton • Abstract Factory • Structurele patronen: • Bridge • Decorator • Composite • Gedragpatronen: • MVC • Iterator • Visitor • Strategy Deze patronen zijn concepten die dichter bij de ontwikkeling zijn (ipv modelleren). In theorie kun je ook design pattern voor modeleren hebben.

  9. Abstract factory pattern • Probleem 2 : • Ik heb een set van producten (zoals Peer, Appel), en varianten (zoals Hollandse Peer/Appel, Belgische Peer/Appel). • Ik wil een set van methodes om objecten uit een variant te genereren. Product Client Appel Peer Ja, het kan via de constructoren maar, een cliënt klasse zou dus alle 4 constructoren moeten kennen  veel koppeling HollandseAppel HollandsePeer BelgischeAppel BelgischePeer

  10. Abstract factory pattern Product <<abstract>> Factory creerAppel(..) : Appel creerPeer(..) : Peer Appel Peer HollandseFactory HollandseAppel HollandsePeer BelgischeFactory BelgischeAppel BelgischePeer

  11. Bridge pattern • Probleem 3: een cliënt gebruikt een klasse T • ze zijn door aparte teams/organisatie ontwikkeld en onderhoud • T kan evolueren • cliënt heeft een stabiele interface naar T nodig <<interface>> Bridge cliënt T 1e poging Inheritence bindt T permanent aan de signatuur van de brug. Stel dat we dit juist niet willen. Wat nu?  ontkoppel de inheritence.

  12. Bridge pattern • Bridge en T kunnen nu onafhankelijk van elkaar geëvolueerd. • Bridge fungeert als een stabiele interface naar T • Operaties van Bridge zijn in termen van T geïmplementeerd • Als T evolueert, moet je eventueel Bridge ook aanpassen. cliënt Bridge T

  13. Decorator pattern • Probleem 4: ik heb een set van “componenten” (aap, kat, …) en een set van features (slim, lui, …). • Ik wil de feature dynamisch te kunnen selecteren. • Ik wil de implementatie van componenten schoon houden. 1e poging Cliënt kan dynamisch kiezen of het een slim of lui variant wil creëren Leidt tot explosie van subklassen. * Cliënt Component Aap Kat LuieAap LuieKat SlimmeAap SlimmeKat

  14. Decorator pattern • Decorator is ook een component! Dus we hoeven de interface naar de client niet te veranderen. • Decorator is een wrapper over een echte component. Component operatie(…) * Cliënt Decorator Aap LuieDecorator Kat SlimmeDecorator • Een decorator injecteert een feature door: • extra attributen (rijker toestand) • operatie(..) te herdefinieren

  15. MVC pattern • Probleem 5: • Ik heb domein-data • Ik wil de data uit een verschillende perspectieven bekijken • De data is bovendien dynamisch (het wordt up de runtime aangepast) • Ik wil dat de views automatisch zich gaan aanpassen. • Ik wil de klasse die de domeindata implementeert niet vervuilen. model views controller

  16. 1e poging… • Operaties om views dynamisch toevoegen of verwijderen. • Hoe weet de views dat de model veranderd heeft? View views * Controller Model * *

  17. MVC View update() zorgt voor het updaten van de view. views * • Parametriseerbaar in • Genoemde klassen en relaties • update • De Controller voegt niets toe in de concept. Zonder controller  Observer Pattern 0..1 Model attach(view) detach(view) notify() notify() { for (v : this.views) v.update() } Controller * *

  18. Voorbeeld van instantie View update() ViewTmpNu * 22o C update tekent: Temperatuur temp attach(view) detach(view) notify() 0..1 Verwarming ViewTmp24u 1 update tekent:

  19. Iterator pattern Probleem 6: Ik wil een generiek interface om te itereren over aggregaatstructuren. <<abstract>> Iterator<E> + hasNext() : boolean + startIter() + next() : E Aggregaat client: Het werkt niet met concurrente cliënten … Aggregaat A = … A.startIter() while (A.hasNext()) { x = next() doe iets met x }

  20. Iterator pattern • Aggregaat-X retourneert Iterator-X, maar deze is ook een Iterator  je hoeft de interface naar client dus niet aan te passen. • Elke client heeft nu zijn eigen iterator  geen (directe) probleem meer met concurrentie (mits de implementatie van Iterator-X dat netjes doet, bijvoorbeeld als cliënt v een element toevoegt terwijl u itereert…). <<abstract>> Iterator<E> + hasNext() : boolean + next() : E Aggregaat-X createIterator() : Iterator-X * Iterator-X<E>

  21. Composite pattern • Twee aparte aggregaties (minder mooi) • Composiet en element hebben vaak gemeenschappelijk attributen (serienr, kleur, …) Probleem 7: ik wil recursie doen over een composiet/element structuur (boom). 1e poging 0..1 Composiet Element * * 0..1 c E c E E

  22. Composite pattern impliciet herdefinitie van bewerk 0..1 componenten Composiet add(component) remove(componen) <<abstract>> Component bewerk(x) * Element • Parametriseerbaar in • Component, Composiet, Element • bewerk (op de composiet en element zijde) • Gemeenschappelijk attributen  in Component

  23. Voorbeeld van instantie 0..1 producten Pakket add(product) remove(product) <<abstract>> Product naam getPrijs() * Item prijs getPrijs() getPrijs() { return prijs } getPrijs() { s = 0for (c : this.producten) s += c.getPrijs() return s}

  24. Visitor pattern • Probleem 8: ik wil recursie doen over een boom • de boom heeft meerdere soorten van composietknopen en elementen; de bewerking per soort is misschien anders. Voorbeeld: • ik wil de recursie niet steeds uitschrijven KortingsPakket SeizoensPakket * Product Pakket VerseGroente Item Blik

  25. Visitor pattern Visitor visit(composietA, subresults) : Result visit (composietB, subresults) : Result visit (elementC) : Result visit (elementD) : Result … Component accept(visitor) : Result Visitor_berekening_X Visitor_berekening_Y

  26. Voorbeeld accept(visitor) { result.clear() for (c : this.producten) result.add(c.accept(visitor) ) return visitor.visit(this,result) } KortingsPakket SeizoensPakket * Product accept(visitor) Pakket VerseGroente Item Blik • accept implementeert recursie • het hoeft 1x geprogrameerd • de implementatie is wel verspreid over verschillende klassen  accept(visitor) { return visitor.visit(this) }

  27. Voorbeeld Visitor visit (kortingspakket,subresultaten) visit (seizoenspakket,subresultaten) visit (verseGroente) visit (blik) TestMember_Visitor x : Product visit(blik) { return (x==blik) } checkt of x een item of een pakket in een product. visit (kortingspakket, subresultaten) { return (x==kortingspakket) || subresultaten.contains(True) } Top level aanroep: memberVisitor.x = een product x y.accept(memberVisitor)

  28. Voorbeeld Visitor visit (kortingspakket,subresultaten) visit (seizoenspakket,subresultaten) visit (verseGroente) visit (blik) Visitor_prijs visit(blik) {return blik.getPrijs() } visit(kortingspakket,subresultaten) { s = som van subresultaten k = kortingspakket.getKorting() return percent(100 – k , s) }

  29. Strategy pattern • Probleem 9 : een cliënt heeft verschillende varianten van een algoritme A nodig. • Direct de varianten in de cliënt inbouwen?  niet altijd een goed idee. Strategie algoritme(…) Cliënt Variant-A Variant-B De cliënt kan dynamisch kiezen tussen verschillende varianten…

  30. Template method pattern • Probleem 10: ik implementeer een algoritme. Voor sommige stappen zijn er varianten. Ik wil echter de keuze uitstellen tot de runtime. client de skelet van de algoritme <<abstract>> Algorithm templateMethod(…) step1(…) step2(…) … templateMethod(…) { … step1(…) … step2(…) … } Variant-A Variant-B Varianten implementeren de stappen, maar herdefinieeren templateMethod niet.

More Related