Programmering

Observer og Observable

Her er problemet: Du designer et program, der gengiver data, der beskriver en tredimensionel scene i to dimensioner. Programmet skal være modulært og skal tillade flere, samtidige visninger af den samme scene. Hver visning skal kunne vise scenen fra et andet udsigtspunkt under forskellige lysforhold. Mere vigtigt er det, at hvis en del af den underliggende scene ændres, skal synspunkterne opdatere sig selv.

Ingen af ​​disse krav udgør en uoverstigelig programmeringsudfordring. Hvis koden, der håndterer hvert krav, skulle skrives de novodog vil det tilføje væsentligt arbejde til den samlede indsats. Heldigvis leveres support til disse opgaver allerede af Java-klassebiblioteket i form af interface Observer og klasse Observerbar- både inspireret af kravene i MVC-arkitekturen.

Model / View / Controller (MVC) -arkitekturen

Model / View / Controller-arkitekturen blev introduceret som en del af Smalltalk, et populært objektorienteret programmeringssprog opfundet af Alan Kay. MVC blev designet til at reducere den krævede programmeringsindsats for at opbygge systemer ved hjælp af flere, synkroniserede præsentationer af de samme data. Dets centrale egenskaber er, at modellen, controllerne og visningerne behandles som separate enheder, og at ændringer, der er foretaget i modellen, automatisk skal reflekteres i hver af visningerne.

Ud over det programeksempel, der er beskrevet i indledningsafsnittet ovenfor, kan Model / View / Controller-arkitekturen bruges til projekter som følgende:

  • En grafpakke, der indeholder samtidige søjlediagram-, linjediagram- og cirkeldiagramvisninger af de samme data.
  • Et CAD-system, hvor dele af designet kan ses i forskellige forstørrelser, i forskellige vinduer og i forskellige skalaer.

Figur 1 illustrerer MVC-arkitekturen i sin mest generelle form. Der er en model. Flere controllere manipulerer modellen; flere visninger viser dataene i modellen og ændres, når tilstanden for modellen ændres.

Figur 1. Model / View / Controller-arkitekturen

Fordele ved MVC

Model / View / Controller-arkitekturen har flere fordele:

  • Der er en klart defineret adskillelse mellem komponenter i et program - problemer i hvert domæne kan løses uafhængigt.
  • Der er en veldefineret API - alt, hvad der bruger API korrekt, kan erstatte enten modellen, visningen eller controlleren.
  • Bindingen mellem modellen og visningen er dynamisk - den forekommer ved kørselstid snarere end på kompileringstidspunktet.

Ved at inkorporere MVC-arkitekturen i et design kan stykker af et program designes separat (og designet til at gøre deres job godt) og derefter bundet sammen på kørselstid. Hvis en komponent senere anses for at være uegnet, kan den udskiftes uden at påvirke de andre stykker. Kontrast dette scenario med den monolitiske tilgang, der er typisk for mange hurtige og beskidte Java-programmer. Ofte indeholder en ramme hele tilstanden, håndterer alle begivenheder, udfører alle beregningerne og viser resultatet. Således er det i alle, men de enkleste af sådanne systemer, ikke trivielt at foretage ændringer.

Definition af delene

Modellen er det objekt, der repræsenterer dataene i programmet. Den administrerer dataene og udfører alle transformationer på disse data. Modellen har ingen specifik viden om hverken dens controllere eller dens synspunkter - den indeholder ingen interne referencer til nogen af ​​dem. Systemet påtager sig snarere ansvaret for at opretholde forbindelser mellem modellen og dens synspunkter og underrette synspunkterne, når modellen ændres.

Udsigten er det objekt, der styrer den visuelle visning af de data, der er repræsenteret af modellen. Det producerer den visuelle repræsentation af modelobjektet og viser dataene for brugeren. Det interagerer med modellen via en henvisning til selve modelobjektet.

Controlleren er det objekt, der tilvejebringer midlerne til brugerinteraktion med de data, der er repræsenteret af modellen. Det giver de midler, hvormed ændringer foretages, enten til informationen i modellen eller til udseendet af udsigten. Det interagerer med modellen via en henvisning til selve modelobjektet.

På dette tidspunkt kan et konkret eksempel være nyttigt. Overvej som et eksempel det system, der er beskrevet i indledningen.

Figur 2. Tredimensionalt visualiseringssystem

Systemets centrale stykke er modellen for den tredimensionelle scene. Modellen er en matematisk beskrivelse af hjørnerne og ansigterne, der udgør scenen. Dataene, der beskriver hvert toppunkt eller ansigt, kan ændres (måske som et resultat af brugerinput eller en sceneforvrængning eller morphing-algoritme). Der er dog ingen forestilling om synspunkt, visningsmetode (wireframe eller solid), perspektiv eller lyskilde. Modellen er en ren repræsentation af de elementer, der udgør scenen.

Den del af programmet, der omdanner dataene i modellen til et grafisk display, er udsigten. Visningen inkorporerer den faktiske visning af scenen. Det er den grafiske gengivelse af scenen fra et bestemt synspunkt under særlige lysforhold.

Controlleren ved, hvad der kan gøres med modellen og implementerer brugergrænsefladen, der gør det muligt at starte denne handling. I dette eksempel kan et kontrolpanel til dataindtastning tillade brugeren at tilføje, ændre eller slette hjørner og ansigter.

Observer og Observable

Java-sproget understøtter MVC-arkitekturen med to klasser:

  • Observer: Ethvert objekt, der ønsker at blive underrettet, når tilstanden for et andet objekt ændres.
  • Observerbar: Ethvert objekt, hvis tilstand kan være af interesse, og i hvilket et andet objekt kan registrere en interesse.

Disse to klasser kan bruges til at implementere meget mere end bare MVC-arkitekturen. De er egnede til ethvert system, hvor objekter automatisk skal underrettes om ændringer, der forekommer i andre objekter.

Typisk er modellen en undertype af Observerbar og udsigten er en undertype af Observer. Disse to klasser håndterer MVCs automatiske underretningsfunktion. De giver den mekanisme, hvormed visningerne automatisk kan underrettes om ændringer i modellen. Objektreferencer til modellen i både controlleren og visningen giver adgang til data i modellen.

Observer og observerbare funktioner

Følgende er kodelister for observatøren og observerbare funktioner:

Observer

  • offentlig ugyldig opdatering (Observable obs, Object obj)

    Kaldes, når der er sket en ændring i den observerbare tilstand.

Observerbar

  • public void addObserver (Observer obs)

    Føjer en observatør til den interne liste over observatører.

  • public void deleteObserver (Observer obs)

    Sletter en observatør fra den interne liste over observatører.

  • offentlig ugyldig deleteObservers ()

    Sletter alle observatører fra den interne liste over observatører.

  • public int countObservers ()

    Returnerer antallet af observatører på den interne observatørliste.

  • beskyttet tomrum sætChanged ()

    Indstiller det interne flag, der angiver, at denne observerbare har ændret tilstand.

  • beskyttet tomrum clearChanged ()

    Rydder det interne flag, der angiver, at dette observerbare har ændret tilstand.

  • offentlig boolsk hasChanged ()

    Returnerer den boolske værdi sand, hvis denne observerbare har ændret tilstand.

  • public void notifyObservers ()

    Kontrollerer det interne flag for at se, om den observerbare har ændret tilstand og underretter alle observatører.

  • public void notifyObservers (Objekt obj)

    Kontrollerer det interne flag for at se, om den observerbare har ændret tilstand og underretter alle observatører. Videregiver det objekt, der er angivet i parameterlisten, til underrette() observatørens metode.

Dernæst ser vi på, hvordan man opretter en ny Observerbar og Observer klasse, og hvordan man binder de to sammen.

Udvid en observerbar

En ny klasse af observerbare objekter oprettes ved at udvide klassen Observerbar. Fordi klasse Observerbar allerede implementerer alle de metoder, der er nødvendige for at tilvejebringe den ønskede opførsel, behøver den afledte klasse kun tilvejebringe en eller anden mekanisme til justering og adgang til den observerbare objekts interne tilstand.

I ObservableValue nedenfor, er den interne tilstand af modellen fanget af heltal n. Denne værdi er kun tilgængelig (og, vigtigere, modificeret) gennem offentlige accessors. Hvis værdien ændres, påkalder det observerbare objekt sit eget setChanged () metode for at indikere, at tilstanden for modellen er ændret. Derefter påberåber det sig sit eget notifyObservers () metode for at opdatere alle de registrerede observatører.

Notering 1. ObservableValue

 import java.util.Observable; offentlig klasse ObservableValue udvides Observable {private int n = 0; public ObservableValue (int n) {this.n = n; } public void setValue (int n) {this.n = n; setChanged (); notifyObservers (); } public int getValue () {return n; }} 

Implementere en observatør

En ny klasse af objekter, der observerer ændringer i tilstanden for et andet objekt, oprettes ved at implementere Observer interface. Det Observer interface kræver, at en opdater () metode tilvejebringes i den nye klasse. Det opdater () metode kaldes, når den observerbare ændrer tilstand og meddeler denne kendsgerning ved at kalde dens notifyObservers () metode. Observatøren skal derefter forhøre det observerbare objekt for at bestemme dets nye tilstand og i tilfælde af MVC-arkitekturen justere dets syn passende.

I det følgende TextObserver notering, den underrette() Metoden kontrollerer først for at sikre, at den observerbare, der har annonceret en opdatering, er den observerbare, som denne observatør observerer. Hvis det er, læser det derefter den observerbare tilstand og udskriver den nye værdi.

Notering 2. TextObserver

 importere java.util.Observer; import java.util.Observable; offentlig klasse TextObserver implementerer Observer {private ObservableValue ov = null; offentlig TextObserver (ObservableValue ov) {this.ov = ov; } offentlig ugyldig opdatering (Observable obs, Object obj) {if (obs == ov) {System.out.println (ov.getValue ()); }}} 

Bind de to sammen

Et program underretter et observerbart objekt, som en observatør ønsker at blive underrettet om ændringer i dets tilstand ved at kalde det observerbare objekt addObserver () metode. Det addObserver () metoden tilføjer observatøren til den interne liste over observatører, der skal underrettes, hvis tilstanden for de observerbare ændringer ændres.

Eksemplet nedenfor, der viser klasse Main, viser, hvordan man bruger addObserver () metode til at tilføje en forekomst af TextObserver klasse (liste 2) til den observerbare liste, der vedligeholdes af ObservableValue klasse (liste 1).

Annonce 3. addObserver ()

 public class Main {public Main () {ObservableValue ov = new ObservableValue (0); TextObserver til = ny TextObserver (ov); ov.addObserver (til); } offentlig statisk ugyldig hoved (String [] args) {Main m = ny Main (); }} 

Hvordan det hele fungerer sammen

Den følgende række af begivenheder beskriver, hvordan interaktionen mellem en observerbar og en observatør typisk finder sted inden for et program.

  1. Først manipulerer brugeren en brugergrænsefladekomponent, der repræsenterer en controller. Controlleren foretager en ændring af modellen via en public accessor-metode - hvilket er setValue () i eksemplet ovenfor.
  2. Den offentlige adgangsmetode ændrer de private data, justerer modelens interne tilstand og kalder dens setChanged () metode til at indikere, at dens tilstand er ændret. Derefter kalder det notifyObservers () at underrette observatørerne om, at det er ændret. Opkaldet til notifyObservers () kunne også udføres andetsteds, f.eks. i en opdateringssløjfe, der kører i en anden tråd.
  3. Det opdater () metoder kaldes på hver af observatørerne, hvilket indikerer, at der er sket en ændring i tilstanden. Observatørerne får adgang til modelens data via modelens public accessor-metoder og opdaterer deres respektive synspunkter.

Observer / observerbar i en MVC-arkitektur

Lad os nu overveje et eksempel, der demonstrerer, hvordan observerbare og observatører typisk arbejder sammen i en MVC-arkitektur. Ligesom modellen i Observerbar værdi (Liste 1) modellen i dette eksempel er meget enkel. Dens interne tilstand består af en enkelt heltal værdi. Staten manipuleres udelukkende via accessor-metoder som dem i Observerbar værdi. Koden til modellen findes her.

Oprindeligt blev der skrevet en simpel tekstvisning / controller-klasse. Klassen kombinerer funktionerne i både en visning (den viser tekstværdien af ​​den aktuelle tilstand for modellen) og en controller (det giver brugeren mulighed for at indtaste en ny værdi for status for modellen). Koden findes her.

Ved at designe systemet ved hjælp af MVC-arkitekturen (i stedet for at indlejre koden til modellen, visningen og tekstcontrolleren i en monolitisk klasse) kan systemet let redesignes til at håndtere en anden visning og en anden controller. I dette tilfælde blev en skydervisning / controller-klasse skrevet. Skyderens position repræsenterer værdien af ​​den aktuelle tilstand af modellen og kan justeres af brugeren for at indstille en ny værdi for tilstanden for modellen. Koden findes her.

Om forfatteren

Todd Sundsted har skrevet programmer, siden computere blev tilgængelige i stationære modeller. Selvom det oprindeligt var interesseret i at oprette distribuerede objektapplikationer i C ++, flyttede Todd til Java-programmeringssproget, da Java blev det oplagte valg for den slags ting.

Denne historie, "Observer and Observable" blev oprindeligt udgivet af JavaWorld.