Chapter 15
Designmønstre

Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark


September 2001


Abstract
Previous lecture
Index References Contents
Genbrug og objekt-orienteret programmering er knyttet tæt til hinanden. Det har imidlertid vist sig, at genbrug på enkelt-klasse niveau ikke har givet så stort udbyttet, som man har drømt om. Genbrug af mønstre mellem klasser, såkaldte design mønstre eller mini-arkitekturer, er en meget lovende udvikling. I denne lektion vil vi introducerer de basale ideer omkring 'design patterns', og vi vil se på en række udvalgte eksempler på mønstre


Genbrug

Genbrug
Slide Note Contents Index
References 
Genbrug af programmer, eller dele af programmer, er en gammel drøm. Her ser vi overordnet på et antal forudsætninger for at genbrug vil kunne lykkes

Genbrug af eksisterende programdele frem for udvikling af nye

  • Forudsætninger for genbrug:

    • At finde det man har brug for

    • At forstå det man har fundet

    • At modificere det forståede, så det passer til det aktuelle behov

    • At sammensætte det modificerede med øvrige programkomponenter

Genbrug i forhold til objekt-orienteret programmering
Slide Note Contents Index
References 
Genbrug af klasser er et af de store håb ved objekt-orienteret programmering. Genbrug af klasser er bedre end blot genbrug af procedurer. Men det ville være endnu bedre at kunne genbruge større enheder, såsom grupper af samarbejdende klasser eller hele programmer. Dette er den grundliggende problemstilling i denne lektion

Genbrugspotentialet er en afgørende motivationsfaktor for overgangen til objekt-orienteret programmering

  • Genbrug af hvad?

    • Enkeltklasser

      • Et af de oprindelige idealer omkring OOP

    • Et objekt-orienteret design

      • Idealet bag design patterns

    • Et objekt-orienteret program

      • Idealet bag objekt-orienterede frameworks


Introduktion gennem et eksempel

Iterator ideen
Slide Note Contents Index
References 
Vi starter konkret ved at se på et designmønster, som vi tidligere har benyttet til gennemløb af lister. Da vi oprindelig så på Iterator omtalte vi det ikke som et designmønster. Det var blot en god løsning på et ikke trivielt problem, som man ofte møder. Men dette viser sig at være den essentielle definition på et designmønster

I forbindelse med gennemløb af lister mødte vi iterator begrebet

Reference

  • Fordele ved at introducere iterator ideen:

    • Udfaktoriserer et ansvarsområde fra listen til en separat klasse

    • Muliggør flere simultane gennemløb af listen ved at instantiere flere iteratorer

    • Forhindrer at klienter direkte tilgår Linkable objekter

Iterator er et eksempel på et designmønster

Iterator opfattet som et designmønster
Slide Note Contents Index
References 
Her vil vi beskrive Iterator opfattet som et designmønster. Vi følger beskrivelses skabelonen fra Gamma og co. 'Design pattern bog', jf. henvisningen herunder. For nogle forhold beskriver vi faktiske egenskaber af Iterator. For andre forhold (kursiverede) beskriver på et mere overordnet niveau hvad de enkelte dele af dokumentationsskabelonen indeholder

Som et designmønster beskrives Iterator i en bredere kontekst end 'gennemløb af en kædet liste'

Beskrivelsen af Iterator følger en skabelon, der er fælles for et helt katalog af mere eller mindre relaterede designmønstre

  • Formål

    • At give sekventiel tilgang til et aggregeret objekt' uden at røbe objektets datarepræsentation

  • Motivation

    • Undgå at udvide aggregate klassen med gennemløbs metoder

    • Motiverende diskussion gennem 'prototypiske eksempler': listeiterator og træiterator

    • Introducerer ideen om polymorf iteration

  • Anvendelighed

    • Mønstret bruges når man vil gennemløbe et aggregeret objekts indhold uden at udstille dets interne repræsentation

    • Understøtter flere samtidige gennemløb

    • Tilbyder gennem polymorfe iteratorer en uniform grænseflade for gennemløb af forskellige aggregerede strukturer

  • Struktur

Betegnelsen 'aggregate' klassen hentyder naturligvis til en klasse som aggregerer en række bestanddele. Vi kalder også undertiden en sådan klasse for en Container.

Polymorf iteration opnås ved at definere én fælles grænseflade (ala Java interface) for en bred klasse af gennemløb. Derved overlever en klientklasse selv om den underliggende liste og/eller iterator skiftes ud

Figure. Strukturdiagram for en iterator, hvor vi anvender generelle begreber i modsætning til listebegreber. Her og i det følgende benytter vi en OMT agtig grafisk notation, ligesom i Design Patterns bogen. Notationen ligner UML, som den kendes fra kurset System Analyse og Design. Vi forklarer notationen i takt med at vi skrider frem. Den stiplede pil fra ConcreteAggregate til ConcreteIterator betyder at ConcreteAggregate har skabt ConcreteIterator

  • Deltagere

    • Kort beskrivelse af deltager klasser i mønstret: Iterator, ConcreteIterator, Aggregate, og ConcreteAggregate

  • Samarbejde

    • Kort beskrivelse af den måde objekterne, som indgår i mønstret, samarbejder med hinanden

  • Konsekvenser

    • Muliggør variationer i gennemløb ved at implementere flere iteratorklasser med sammen grænseflade

    • Gør aggregate klassen simplere, idet funktionalitet udfaktoriseres til Iterator klassen

    • Mere end ét gennemløb kan være aktivt ad gangen idet hver Iterator objekt har sin egen tilstand

  • Implementation

    • Fyldig diskussion af Implementors i forskellige programmeringssprog

  • Eksempel program

    • Illustration af Iterator aspekter gennem konkrete programfragmenter

  • Kendte anvendelser

    • Beskrivelse af publicerede eller kendte programmer, hvor mønstret bliver anvendt i praksis

  • Relaterede mønstre

    • Alternative mønstre, eller mønstre der anvendes sammen med Iterator

Reference
  • Bog om design patterns: 'Design Patterns - Elements of reusable object-oriented software' af Gamma, Helm, Johnson og Vlissides, Addison Wesley, 1995
    The reference above goes to paper material

Design Patterns bogen, som er refereret ovenfor, er den mest kendt og udbredte bog om mønstre. Men der er også en del andre. En del af materialet i disse noter er tilpasset direkte fra denne bog.


Generelt om designmønstre

Hvem er Christopher Alexander?
Slide Note Contents Index
References 
Designmønster interessen kan på en meget direkte måde spores tilbage til arkitektur faget, hvor en enkelt person's ideer har haft afgørende indflydelse på design af ting i vores fysiske verden

Ideerne bag design patterns stammer fra arkitektfaget, hvor Christopher Alexander har udviklet et stort antal design mønstre

  • Christopher Alexander:

    • Professor i arkitektur ved University of California, Berkeley

    • Har skrevet en række bøger, som anviser 'en ny vej' til bedre design

    • Gør op med det rationelle design paradigme, som er baseret på en faseopdelt arbejdsgang:

      • Analyse leder til specifikation, som er grundlag for konstruktion

"Model, process, context and artifact are intertwined aspects of the same system"

"Abstract representations lose details that always end up mattering"

Inspirationen til design pattern kommer fra arkitektur og Alexander

Alexander har imidlertid ikke selv bidraget til patterns inden for software

Hvad er et designmønster?
Slide Note Contents Index
References 
Vi byder her på en konkret definition af designmønster begrebet. Definitionen stammer fra Brad Appletons WWW artikel: 'Patterns and Software: Essential Concepts and Terminology', som er refereret på denne side

The concept designmønster: Et designmønster er et navngiven 'guldkorn' af instruktiv information, som indfanger væsentlige strukturer og indsigt om en succesfuld familie af velafprøvede løsninger på tilbagevendende problemer i en bestemt kontekst, hvor forskellige kræfter kan trække i hver deres retningEt designmønster er en nyttig instruktion, som fortæller hvordan man løser et bestemt problem. Problemet er karakteriseret af, at man møder det igen og igen i bestemte sammenhænge (kontekster). I disse sammenhænge skal der tages mangeartede hensyn, idet der er 'kræfter', som ofte virker i forskellige retninger. Løsningen på problemet er karakteriseret af at den er velafprøvet. Man kender altså konsekvenserne af at anvende den beskrevne løsning på problemet.

  • Værd at bemærke:

    • Navngiven: Fremmer muligheden for sikker kommunikation om mønstret

    • Guldkorn: Understreger værdien af mønstret

    • Tilbagevendende problemer: Mønstret skal adressere et problem som optræder igen og igen

    • Velafprøvede løsninger: Løsninger som beviseligt virker i et antal eksisterende og velkendte systemer

    • Kontekst: Forudsætninger og situation inden designmønstret anvendes

    • Forskelligt rettede kræfter: Hensyn og forhold, som ofte er i indbyrdes konflikt med hinanden

Reference

Egenskaber ved et godt designmønster
Slide Note Contents Index
References 
Vi lister her de fire væsentligste egenskaber ved designmønstre. Man kan også tænke på disse som kriterier for, at noget er et design pattern.

  • Det løser et problem

    • Ikke blot et abstrakt princip eller strategi

  • Det er et velafprøvet koncept

    • Ikke teori eller spekulation

  • Den underliggende løsning er ikke oplagt

    • Rene trivialiteter fortjener ikke betegnelsen 'designmønster'

  • Mønstret har en betydelig menneskelig komponent

    • De bedste designmønstre appellerer til æstetik og anvendelighed

Designmønstre på forskellige niveauer
Slide Note Contents Index
References 
Designmønstre kan optræde på vidt forskellige abstraktionsniveauer. Man kan videre observere, at mønstre kan optræde andre steder end i design og programmering. Man taler således om analysemønstre

  • Arkitekturmønstre

    • En fundamental strukturel organisering af et program eller et helt softwaresystem

  • Mikroarkitekturer

    • Almindeligt forekommende strukturer af et mindre antal kommunikerende objekter, som løser et generelt design problem i en bestemt kontekst

  • Idiom

    • En typisk, etableret og ofte sprogafhængig udtryksform, hvis betydning ikke nødvendigvis gennemtænkes ved hver anvendelse

I resten af denne lektion samler interessen sig om designmønstre på mikroarkitektur niveau

Reference

Katalogisering af design patterns
Slide Note Contents Index
References 
Det væsentligste bidrag af Design Pattern bogen, som vi har omtalt ovenfor (og tilsvarende bøger) er at den katalogiserer designmønstre til gavn og glæde for softwareudviklere og studerende. Design Pattern bogen er således et katalog bestående af 23 forskellige mønstre, der beskrives ud fra en standard disposition

Det er et væsentlig karakteristika ved design patterns at disse dokumenteres ud fra en standard disposition

Pattern navn og klassifikation

Deltagere

Hensigt

Samarbejde, herunder interaktionsdiagram

Andre navne for mønstret

Konsekvenser

Motivation

Eksempelprogrammer

Anvendelse

Kendte anvendelser

Struktur, herunder klassediagram

Relaterede mønstre


Udvalgte designmønstre

Singleton (1)
Slide Note Contents Index
References 
Designmønstret, der hedder Singleton, garanterer at der kun kan laves én instans af en klasse

Singleton er et designmønster som har til formål at sikre, at der højst kan laves én instans af en bestemt klasse

  • Naiv løsning:

    • I stedet for at instantiere et objekt refereres til en global variabel, som refererer til én fælles instans af objektet

  • Idéer som gør klassen C til en Singleton:

    • Konstruktoren i C fjernes fra klientgrænsefladen

    • Instansen af C skabes og returneres gennem en klasse metode (static)

    • Instansen refereres fra en privat klassevariabel (static variabel) i C

I den naive løsning taler vi om en global variabel, som indeholder den ene instans vi vi er interesseret i. Vi kan observere, at sådanne globale variable ikke findes i Java. Det nærmeste vi kommer er statiske (klasse) variable. Sådanne kan helt klart anvendes til formålet. Singleton er dog en anelse smartere end blot en statisk, globalt tilgængelig variabel, som refererer til 'det enestående objekt'

Figure. Et klassediagram for Singleton designmønstret. Det er skitseret i boksen til højre hvordan instance metoden laver en memoriseret instans. (Bemærk at vi ikke følger præcis Java syntaks i dette eller de følgende diagrammer).

Singleton (2)
Slide Note Contents Index
References 
Vi fortsætter her behandlingen af designmønstret Singleton. Vi koncentrerer os om en Java implementation af singleton

Java's static tillader en ligefrem implementation af Singleton mønstret

Program: Skabelonen for en Singleton klasse i Java. Ifølge mønstret fra Design Patterns bogen bør konstruktoren i Singleton klassen være protected. Dermed kan den anvendes fra evt. subklasser. Men på grund af Java's specielle regler om protectede egenskaber i en klasse (hvor disse også er pakkesynlige) skal konstruktoren være privat for at sikre, at ingen klient får lejlighed til at instantiere en singleton klasse
class Singleton {

  protected int singletonData;
  private static Singleton uniqueInstance = null;
  
  private Singleton(){
    // initialisering af data:
    singletonData = 5;
  }

  public static Singleton instance() {
    if (uniqueInstance == null)
       uniqueInstance = new Singleton();
    return(uniqueInstance);
  }

  // Singleton instansmetoder:
  // ...

} // end Singleton

Program: Anvendelse af en Singleton klasse fra en anden klasse i Java. Vi tester om s2 og s3 virkelig refererer til det samme objekt, den eneste instans af Singleton, som vi tillader at instantiere
class SingletonDemo {

  public static void main(String[] args){
    // Singleton s1 = new Singleton();  // compile time error!
    Singleton s2 = Singleton.instance();
    Singleton s3 = Singleton.instance();

    if (s2 == s3)
      System.out.println("Objekteren s2 og s3 refererer til samme objekt");
    else
      System.out.println("Problemer!");
  }
} // end SingletonDemo

  • Konsekvenser:

    • Kontrolleret tilgang til instansen

      • Den ene instans er indkapslet og beskyttet i klassen Singleton

      • Objektet tilgås gennem en metode (beregnet tilgang) i stedet for ved aflæsning af en variabel (data tilgang)

    • Reduceret navnerum

      • Vi undgår at at skulle dedikere en offentlig kendt global variabel til at referere til den ene instans

    • Tillader let generalisering til 'højst n instanser'

Factory Method (1)
Slide Note Contents Index
References 
Dette designmønster retter sig mod central kontrol af instantiering af klasser. I stedet for at at have mange konkrete instantieringer af 'en produktklasse' rundt omkring i et program overlades ansvaret for produkt instantiering til et fabrikationsobjekt, som foretager instantieringen for os. Dette fabrikationsmellemled skaber en betydelig fleksibilitet. F.eks. kan vi med ét slag sørge for, at en anden klasse end den oprindeligt tiltænkte, bliver instantieret

Designmønstret Factory Method understøtter skabelse af produktobjekter gennem et fabrikationsobjekt

Fabrikationsobjektet overlader det til en subklasse af bestemme typen af de fabrikerede objekter

  • Anvendes:

    • Når vi ønsker at uddelegere ansvaret for objektskabelse til et fabrikationsobjekt (en Creator)

    • Når fabrikationsobjektet ikke nødvendigvis har konkret viden om hvilken type af objekter det ønsker at skabe

      • Fabrikationsobjektet er abstrakt, og overlader det som sådan til subklasser at foretage den egentlige skabelse af produktobjekter

    • Når vi dynamisk på køretidspunktet ønsker at 'slå over i' skabelse af en anden slags produkter

Figure. Klassediagram for Factory Method designmønstret. Vi ser en abstrakt Creator (factory, altså fabrikations) klasse hvor operationen anOperation skaber et produktobjekt gennem den abstrakte metode factoryMethod.

Tænk på Creator klassen som en eller anden 'applikations klasse', der har behov for at skabe en produktklasse. Creatorklassen, som er abstrakt og dermed på et højt abstraktionsniveau, har ikke viden om, hvilket produktobjekt der skal skabes. Det overlades til en subklasse af Creator klassen at tage denne beslutning.

Forskellige subklasser af Creator klassen kan instantiere forskellige produkter, som måske alle har et bestemt Interface tilfælles. Man kan også forestilige sig, at instantieringen kan variere hen over tid på anden vis.

Bemærk at klasser og metoder, som er sat med kursiv skrift, er abstrakte. Den stiplede pil fra ConcreteCreator til ConcreteProduct fortæller, at creatoren skaber et produktobjekt

Factory Method (2)
Slide Note Contents Index
References 
Vi ser her på konsekvenserne af at bruge mønstret Factory Method

  • Konsekvenser:

    • Undgår at fastlodde mange, specifikke instantieringer af produktklasser i vores program

      • Ved at ændre fabrikationsmetoden kan vi - på ét centralt sted - foranledige en anderledes instantiering

    • Tillader os at forudannoncere metoder i en abstrakt Creator klasse, som foretager instantieringer.

      • Selve objektskabelsen foretages i metoder, som defineres fuldt ud i subklasser af Creatoren

    • Gør det muligt at variere objekt-fabriktionen ved at have flere specialiseringer af Creator klassen (polymorfi, dynamisk binding)

Composite (1)
Slide Note Contents Index
References 

Composite er et designmønster som sammensætter objekter i hierarkier af helheder og dele

Manipulation af helheder afstedkommer tilsvarende manipulation af delene

Figure. Et velkendt eksempel på brugen af Composite design mønstret på grafiske objekter, hvoraf nogle (containere) kan indeholde andre grafiske objekter. Klassen Picture er en sådan container, som altså kan indholde andre Picture objekter, og ultimativt et antal Line, Rectangle og Text objekter. På figuren symboliserer diamanten som udgår fra Picture aggregering. Den sorte cirkel i enden af relationen (op imod den abstrakte klasse Graphics) symboliserer flere mulige grafik bestanddele.

Composite er kendt fra Container klasser i objekt-hierarkiet af brugergrænseflade komponenter i Java AWT og Swing

I Component klassehierarkiet svarer Container til klassen Picture ovenfor. Klassen Graphic svarer i AWT til Component. Metoden Draw i diagrammet modsvares af en række forskellige metoder i Component, såsom paint, repaint og print

References

Composite (2)
Slide Note Contents Index
References 
Her fortsættes behandlingen af Composite designmønstret

Figure. Det generelle strukturdiagram for Composite designmønstret. Det er værd at bemærke, at strukturen som er vist generelt definerer et træ, hvor Composite objekter er de indre knuder, og hvor Leaf objekter (som navnet antyder) er blade

Konsekvenser:

  • Når der opereres på et Composite-objekt opereres der 'automatisk' på alle del-objekter

  • Klienter af Component opnår et homogent syn på sammensatte og atomare objekter

  • Klienten skal ikke bekymre sig om andet end helhedsobjektets operationer

  • Det er et problem at understøtte add, delete og getchild på atomare Leaf objekter

Man kan spørge sig selv om, hvorfor det er et problem at understøtte metoder add, delete og getchild på Leaf objekter. Disse operationer nedarves naturligivs fra Component klassen. Problemet er imidlertid, at de ikke giver mening på Leaf objekter; Et Leaf objekt er et terminalt Component objekt, og er som sådan karakteriseret af at det ikke kan have 'børn'.

Command (1)
Slide Note Contents Index
References 
Vi ser her på Command mønstret, som materialserer en handling i et objekt

Indkapsler og materialiserer en handling (kommando) til et objekt

Tillader repræsentation af 'undo' information i lister af kommandoobjekter

Fremmer en løsere kobling mellem f.eks. brugergrænseflade elementer (f.eks. menuer) og den bagvedliggende applikation

Figure. Et klassediagram for Command design mønstret. Læg mærke til grænsefladen af Command: execute, undo og redo. Execute virker her på et objekt, som er 'receiver' af kommandoens handlinger. Altså sker kommandoens påvirkning i dette mønster på receiver objektet.

Vi ser endvidere at en kommando er en del af en Invoker. Invoker kan f.eks. være et menuitem, som indeholder (eller refererer til) et kommandoobjekt, som udføres når menuen aktiveres

Command (2)
Slide Note Contents Index
References 

  • Konsekvenser:

    • Homogen grænseflade mellem Invokers (såsom Menuitems) og Commands.

    • Kommandoer i sekvens kan sammensættes til en Composite Command via design mønstret Composite

    • Der kan implementeres et transaktionsbegreb omkring sammensatte kommandoer

    • Udførte kommandoer kan kopieres og indsættes i en kommando historieliste

    • Kan anvendes til en multi-niveau undo og multi-niveau redo facilitet

    • Kopiering af kommandoer kan håndteres via et designmønster, der hedder Prototype

Command (3)
Slide Note Contents Index
References 
Vi slutter Command mønstret af med at sammenligne det med Java AWT's event listeners

  • Event listeners i AWT

    • Typisk meget mere grovkornede en Command objekter

    • Har ikke potentialet til at indeholde information, så en kommando kan omgøres

Swing's brugergrænseflade model er - på en løs måde - inspireret af Command designmønstret i forbindelse med udformningen af en undo/redo mekanisme

References

Decorator (1)
Slide Note Contents Index
References 
Decorator er et designmønster hvormed vi dynamisk kan 'udvide et objekt' med nye egenskaber.

Tilføjer egenskaber til et objekt på en dynamisk basis i modsætning til statisk udvidelse af en klasse via nedarvning

Statisk set kan vi tilføje nye egenskaber ved at lave en udvidelse (ved brug af nedarvning mellem klasser). Men dette virker ikke dynamisk, på eksisterende objekter. Ideen bag Decorator er at understøtte udvidelse af eksisterende objekter, på 'run time'.

Figure. Et prototypisk eksempel på Decorator designmønstret, hvor en tekst dekoreres med ramme og scrollbar. Kæden af objekter, hvor de forreste to dekorerer text view objektet. Når der opereres på aBorderDecorator tegnes kanten, hvorefter aScrollDecorator tilsendes samme besked. Når der opereres på aScrollDecorator tegnes scroll bars, hvorefter aTextView sendes samme besked. Når der opereres på aTextView tegnes det tekstuelle syn på objekter (det egentlige arbejde)

Decorator mønstret er et meget mere fleksibelt alternativ til en statisk løsning med udvidelse via nedarvning

Decorator (2)
Slide Note Contents Index
References 
Nu hvor vi har set på den dynamiske objekt-struktur af Decorator vil vi se på (et eksempel på) den statiske klasse-struktur

Figure. Et eksempel på anvendelse af Decorator designmønstret. I eksemplet dekoreres tekst view med scrollbars og border. Når en decorator tegner sig selv tegnes også det dekorerede objekt, som igen kan være en dekorator, eller ultimativ et tekst view objekt i dette eksempel.

En klient, som arbejder på et TextView objekt, skal arbejde med en reference af typen VisualComponent. Da både et TextView og de forskellige decorator objekter er VisualComponents hænger det hele samme rent typemæssig, via typersammenlignelighed reglerne i Java.

Konsekvenser:

  • Mere fleksibel end udvidelse via nedarvning (evt. multipel nedarvning)

  • Det, som naturligt er ét objekt, ender med at være repræsenteret som flere objekter i en kæde

    • Potentielle problemer med objektidentitet

Objekterne i kæden kan siges at delegere arbejde til hinanden. Vi har tidligere i materialet mødt delegering, og vi har konsteret at delegering undertiden er et alternativ til nedarvning. I denne sammenhæng bliver det understreget, at delegering er et mere dynamisk alternativ en nedarvning.

Når en klasse B arver fra A, er instanser af B hele objekter uden nogen form for delobjekter. Når et B-objekt derimod delegerer arbejdet til et A-objekt er der to objekter i spil. På denne måde er identiteten af fænomenet delt ud på to separate objekter, hvilket kan give komplikationer i visse sammenhænge.

Decorator (3)
Slide Note Contents Index
References 
Vi afslutter diskussionen af Decorators med et eksempel, vi tidligere er stødt på, nemlig filter streams i Java bibliotekerne

Måden hvorpå streams kan sættes sammen i 'pipelines' følger Decorator designmønstret

  • Klasserne FilterInputStream og FilterOutputStream er eksempler på Decorators for streams i Java

    • En kæde af filter streams dekorerer en underliggende stream

    • Streamoperationer går igennem kæden af filter streams for at ende i den underliggende streams

    • Klienter kan håndtere et et filterstream objekt som var det det underliggende stream objekt

References

Observer (1)
Slide Note Contents Index
References 
Observer er sikkert den mest kendte (og én af de mest nyttige) designmønstre overhovedet. Vi har studeret den ganske nøje i en tidligere lektion, men vi gentager den her, for at understreget de egenskaber ved Observer, som man skal holde fast i når 'vi har designmønster briller på'

I lektionen om brugergrænseflader studerede vi en organisering af model og syn, som vi kaldte for Observer

Her vil vi resumere de væsentligste aspekter af Observer som designmønster

Figure. Et klassediagram for Observer designmønstret. Subject klassen svarer til Observable, jf. brugergrænseflade lektionen. Når et subjekt objekt er opdateret broadcastes dette til observer objekterne via den abonnementsordning, der er mellem subjekt og observatører. I ConcreteObserver ser vi at update metoden umiddelbar sender beskeden getState i subject objektet, for at finde ud af, hvad der egentlig skete. På næste side ser vi et objekt diagram, hvor disse interaktioner bliver illustreret på en meget klar måde

References

Observer (2)
Slide Note Contents Index
References 
Observer er et mønster med en relativ kompliceret adfærd. Design Patterns bogen klassificerer den som et 'behavioral pattern' (som kontrast til 'structural' og 'creational patterns'). Derfor er det givende at vise en dynamisk model af mønstret, hvor vi ser hvordan subjekt og observer objekter interagerer indbyrdes

Figure. En konkret observatør ændres, hvorved tilstanden i modellen (subject objektet) ændres. Du skal forestille dig, at vi er igang med at operere på en brugergrænseflade, f.eks. at vi trykker på en knap. Derved ændres modellen. Den øverste setState besked er en følge af denne tilstandsændring. (Det er ikke sikkert, at beskeden kommer fra en observatør; Hvis vi følger model-view-controller tankegangen, vil den nok komme fra en listener).

Subject objektet sender sig selv Notify beskeden, som meddeler alle observatører, at modellen er opdateret. Hver observatør henter den fornødne tilstand (eller tilstandsændring) i subject objektet med henblik på at opdatere sig selv

Observer (3)
Slide Note Contents Index
References 
Ligesom vi har gjort for de andre patterns, vil vi også for observers liste de vigtige konsekvenser, som anvendelse af mønstret kan forårsage

Konsekvenser:

  • Abstrakt og minimal kobling mellem Subject og Observer

  • Understøttelse af 'broadcasts' fra Subject objektet

  • Uventede og unuancerede opdateringer af Observer objekter

    • Mindre opdateringer af subjektet kan forårsage kaskader af updates til observatører

    • Updates afspejler ingen viden om, hvad der er ændret i subjekt objektet

Object Adapter (1)
Slide Note Contents Index
References 
Adapter er et nyttigt pattern, som tilpasser grænsefladen af en klasse C til bestemte krav eller forventninger, til en klient. I stedet for at lave klassen om kan vi indskyde et mellemled, som tilpasser C. Vi ser her på en variant af Adapter, som kaldes Object Adapter

Vi har en klasse med brugbar funktionalitet, men med en ikke-brugbar grænseflade

Adapter tilpasser grænsefladen af en klasse til bestemte forventninger af en klient

Figure. Et klassediagram for Adapter, hvor et Adapter objekt tilpasses via en associering til en Adaptee objekt

  • Konsekvenser

    • Tillader os at bruge et objekt i en kontekst, hvor det rent interfacemæssigt ikke fitter

    • Om nødvendigt kan Adapter klasse tilføje (udvides med) ny funktionalitet i forhold til Adaptee klassen

    • En Adapter kan tilpasse grænsefladen af et helt Adaptee klassehierarki

I forbindelse med, at en Adapter kan tilpasse et helt Adaptee klassehierarki forestiller vi os altså, at Adaptee klassen har en række subklasser. Den ene Adapter, som er organiseret som ovenfor, tilpasser dem alle

Klasse Adapter (2)
Slide Note Contents Index
References 
I stedet for at involvere to objekter af typerne hhv. Adapter og Adaptee kan vi organisere tilpasningen gennem nedarvning. Dette giver en 'Class Adaptor' i kontrast til den ovenfor beskrevne 'Object Adapter'

Figure. En Class Adapter med multipel nedarvning. I Java skal mindst én af Target og Adaptee være et Interface. Det er klart, at det er Target der er kandidat til at være et Interface, idet der jo er betydelig substans vi ønsker at bibringer Adapter fra Adaptee. Typemæssigt ønsker vi dog, at Adapter er en Target. Altså er Adapter en specialisering af Target

  • Konsekvenser:

    • Adaptor kan - om nødvendig - redefinere egenskaber i Adaptee

    • Kun ét objekt er involveret

      • Kontrast til Objekt Adapter

Adapter (3)
Slide Note Contents Index
References 
Vi ser her på konsekvenserne ved at bruge et Adapter designmønster

Er Adaptor klasserne for listener interfaces i AWT
adapters i designmønster forstand?

References

WindowAdapter og tilsvarende tilpasser ikke grænsefladen af en klasse på nogen måde

Derimod bidrager WindowAdapter et al. med en default implementation af et Java Interface

Så svaret er NEJ


Collected references
Contents Index
Iterators and enumerations
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Bog om design patterns: 'Design Patterns - Elements of reusable object-oriented software' af Gamma, Helm, Johnson og Vlissides, Addison Wesley, 1995
The reference above goes to paper material
Brad Appleton: 'Patterns and Software: Essential Concepts and Terminology'
The references above goes to material on the Internet
Wait notify idiom
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Klassen Container i pakken java.awt
The reference from above goes to Java API pageThe references above goes to material on the Internet
Klassen Component i pakken java.awt
The reference from above goes to Java API pageThe references above goes to material on the Internet
Eksempel på komponenthierarki
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Klassehierarkiet med rod i Component
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Klassen AbstractUndoableEdit i pakken java.swing.undo
The reference from above goes to Java API pageThe references above goes to material on the Internet
Add an undo/redo function to your Java apps with Swing (JavaWorld artikel)
The references above goes to material on the Internet
Om event listeners
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Klassen FilterInputStream i pakken java.io
The reference from above goes to Java API pageThe references above goes to material on the Internet
Klassehierarkierne for InputStream og OutputStream
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Eksempel på brug af stream filtre
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Klassen Observer i klassen java.util
The reference from above goes to Java API pageThe references above goes to material on the Internet
Klassen Observable i klassen java.util
The reference from above goes to Java API pageThe references above goes to material on the Internet
Observer ideen fra lektionen om grafiske brugergrænseflader
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes
Klassen WindowAdapter i pakken java.awt.event
The reference from above goes to Java API pageThe references above goes to material on the Internet
Anvendelse af adapter klasse i event listeners
The reference above goes to a lecture note pageThe reference above points to an earlier page in the lecture notes

 

Chapter 15: Designmønstre
Course home     Author home     About producing this web     Previous lecture (top)     Next lecture (top)     Previous lecture (bund)     Next lecture (bund)     
Generated: March 31, 2008, 12:10:00