Programiranje

Opazovalec in opazovalec

Tu je težava: načrtujete program, ki bo upodabljal podatke, ki opisujejo tridimenzionalni prizor v dveh dimenzijah. Program mora biti modularen in mora omogočati več hkratnih pogledov iste scene. Vsak pogled mora biti sposoben prikazati prizor z drugega vidika pod različnimi svetlobnimi pogoji. Še pomembneje pa je, da se morajo pogledi sami posodobiti, če se kateri koli del osnovne scene spremeni.

Nobena od teh zahtev ne predstavlja nepremostljivega programskega izziva. Če bi morala biti napisana koda, ki obravnava vsako zahtevo de novovendar bi k skupnim naporom dodal veliko dela. Na srečo podporo za te naloge že ponuja knjižnica razredov Java v obliki vmesnika Opazovalec in razred Opazno- oba delno navdihujejo zahteve arhitekture MVC.

Arhitektura modela / pogleda / krmilnika (MVC)

Arhitektura Model / View / Controller je bila predstavljena kot del Smalltalka, priljubljenega objektno usmerjenega programskega jezika, ki ga je izumil Alan Kay. MVC je bil zasnovan za zmanjšanje programskega napora, potrebnega za izdelavo sistemov, ki uporabljajo več sinhroniziranih predstavitev istih podatkov. Njegove osrednje značilnosti so, da so model, krmilniki in pogledi obravnavani kot ločeni entiteti in da bi se morale spremembe v modelu samodejno odražati v vsakem pogledu.

Poleg primera programa, opisanega v uvodnem odstavku zgoraj, se lahko arhitektura modela / pogleda / krmilnika uporablja za projekte, kot so naslednji:

  • Paket grafov, ki vsebuje sočasne poglede istih podatkov v obliki črtnega grafikona, črtnega grafikona in tortnega diagrama.
  • Sistem CAD, pri katerem je mogoče dele zasnove gledati z različnimi povečavami, v različnih oknih in v različnih merilih.

Slika 1 prikazuje arhitekturo MVC v najbolj splošni obliki. Obstaja en model. Z modelom manipulira več krmilnikov; več pogledov prikazuje podatke v modelu in se spreminja, ko se stanje modela spremeni.

Slika 1. Arhitektura modela / pogleda / krmilnika

Prednosti MVC

Arhitektura modela / pogleda / krmilnika ima več prednosti:

  • Obstaja jasno določena ločitev med komponentami programa - težave v vsaki domeni je mogoče rešiti samostojno.
  • Obstaja natančno definiran API - vse, kar API uporablja pravilno, lahko nadomesti model, pogled ali krmilnik.
  • Vezava med modelom in pogledom je dinamična - pojavlja se v času izvajanja in ne v času prevajanja.

Z vključitvijo arhitekture MVC v zasnovo se lahko deli programa oblikujejo ločeno (in so zasnovani tako, da dobro opravljajo svoje delo), nato pa jih med izvajanjem povežejo med seboj. Če se kasneje šteje, da je komponenta neprimerna, jo je mogoče zamenjati, ne da bi to vplivalo na ostale kose. Ta scenarij lahko primerjate z monolitnim pristopom, značilnim za številne hitre in umazane programe Java. Pogosto okvir vsebuje vse stanje, obravnava vse dogodke, opravi vse izračune in prikaže rezultat. Tako pri vseh takšnih sistemih, razen pri najpreprostejših, spreminjanje po dejanskem stanju ni nepomembno.

Opredelitev delov

Model je objekt, ki predstavlja podatke v programu. Upravlja s podatki in izvaja vse njihove transformacije. Model nima posebnega znanja ne o krmilnikih ne o svojih pogledih - ne vsebuje nobenih notranjih sklicev na nobenega. Sistem sam prevzame odgovornost za vzdrževanje povezav med modelom in njegovimi pogledi ter obveščanje o pogledih, ko se model spremeni.

Pogled je objekt, ki upravlja vizualni prikaz podatkov, ki jih predstavlja model. Izdela vizualno predstavitev modela in prikaže podatke uporabniku. Z modelom komunicira prek sklicevanja na sam objekt modela.

Krmilnik je objekt, ki zagotavlja sredstva za interakcijo uporabnika s podatki, ki jih predstavlja model. Zagotavlja sredstva, s katerimi se spreminjajo informacije v modelu ali videz pogleda. Z modelom komunicira prek sklicevanja na sam objekt modela.

Na tej točki je lahko koristen konkreten primer. Za primer poglejmo sistem, opisan v uvodu.

Slika 2. Tridimenzionalni vizualizacijski sistem

Osrednji del sistema je model tridimenzionalne scene. Model je matematični opis oglišč in obrazov, ki sestavljajo sceno. Podatke, ki opisujejo vsako oglišče ali obraz, je mogoče spremeniti (morda kot rezultat uporabnikovega vnosa ali algoritma za popačenje scene ali preoblikovanje). Vendar pa ni pojma stališča, načina prikaza (žični ali masivni), perspektive ali svetlobnega vira. Model je čista predstavitev elementov, ki sestavljajo sceno.

Del programa, ki podatke v modelu pretvori v grafični prikaz, je pogled. Pogled pooseblja dejanski prikaz scene. Je grafična predstavitev prizora z določenega vidika, pod določenimi svetlobnimi pogoji.

Krmilnik ve, kaj je mogoče storiti z modelom, in izvaja uporabniški vmesnik, ki omogoča sprožitev tega dejanja. V tem primeru lahko nadzorna plošča za vnos podatkov uporabniku omogoča dodajanje, spreminjanje ali brisanje točk in obrazov.

Opazovalec in opazovalec

Jezik Java podpira arhitekturo MVC z dvema razredoma:

  • Opazovalec: Vsak objekt, ki želi biti obveščen, ko se stanje drugega predmeta spremeni.
  • Opazno: Vsak predmet, katerega stanje je lahko zanimivo in pri katerem lahko drug predmet registrira interes.

Ta dva razreda lahko uporabimo za mnogo več kot le arhitekturo MVC. Primerni so za vsak sistem, v katerem je treba predmete samodejno obvestiti o spremembah, ki se pojavijo pri drugih predmetih.

Običajno je model podtip Opazno in pogled je podvrsta Opazovalec. Ta dva razreda obravnavata funkcijo samodejnega obveščanja MVC. Zagotavljajo mehanizem, s katerim lahko poglede samodejno obveščamo o spremembah v modelu. Sklici predmetov na model v krmilniku in pogledu omogočajo dostop do podatkov v modelu.

Opazovalne in opazovane funkcije

Sledijo seznam kod za opazovalca in opazovane funkcije:

Opazovalec

  • posodobitev javne praznine (Observable obs, Object obj)

    Poklican, ko je prišlo do spremembe stanja opaznega.

Opazno

  • public void addObserver (Observer obs)

    Doda opazovalca na notranji seznam opazovalcev.

  • public void deleteObserver (Observer obs)

    Izbriše opazovalca z notranjega seznama opazovalcev.

  • public void deleteObservers ()

    Izbriše vse opazovalce z notranjega seznama opazovalcev.

  • javni int countObservers ()

    Vrne število opazovalcev na notranjem seznamu opazovalcev.

  • protected void setChanged ()

    Nastavi notranjo zastavico, ki označuje, da je stanje tega opaznega spremenjeno.

  • zaščitena praznina clearChanged ()

    Počisti notranjo zastavico, ki označuje, da je stanje opaznega stanja spremenjeno.

  • javno logično hasChanged ()

    Vrne logično vrednost true, če je to opazljivo stanje spremenilo.

  • javna void notifyObservers ()

    Preveri notranjo zastavico, da ugotovi, ali je opazovano stanje spremenilo, in obvesti vse opazovalce.

  • javna void notifyObservers (predmet predmeta)

    Preveri notranjo zastavico, da ugotovi, ali je opazovano stanje spremenilo, in obvesti vse opazovalce. Prenese objekt, naveden na seznamu parametrov, v obvestiti() metoda opazovalca.

Nato si bomo ogledali, kako ustvariti novo Opazno in Opazovalec razredu in kako povezati oba.

Razširite opazovano

Z razširitvijo razreda se ustvari nov razred opazovanih predmetov Opazno. Ker razred Opazno že izvaja vse metode, potrebne za zagotavljanje želenega vedenja, izpeljani razred mora zagotoviti le mehanizem za prilagajanje in dostop do notranjega stanja opaznega predmeta.

V ObservableValue spodaj, notranje stanje modela zajema celo število n. Do te vrednosti se dostopa (in, kar je še pomembneje, spremeni) le prek javnih dostopnikov. Če se vrednost spremeni, opazovani objekt prikliče svojega setChanged () metoda, ki označuje, da se je stanje modela spremenilo. Nato prikliče svoje notifyObservers () za posodobitev vseh registriranih opazovalcev.

Seznam 1. ObservableValue

 uvoz java.util.Observable; javni razred ObservableValue razširi Observable {private int n = 0; public ObservableValue (int n) {this.n = n; } javna void setValue (int n) {this.n = n; setChanged (); notifyObservers (); } public int getValue () {return n; }} 

Izvedite opazovalca

Z izvedbo datoteke se ustvari nov razred predmetov, ki opazujejo spremembe stanja drugega predmeta Opazovalec vmesnik. The Opazovalec vmesnik zahteva, da nadgradnja() metoda v novem razredu. The nadgradnja() metoda se pokliče vsakič, ko se opazno stanje spremeni, in to dejstvo sporoči s klicem svojega notifyObservers () metoda. Nato mora opazovalec zaslišati opazovani objekt, da ugotovi njegovo novo stanje, in v primeru arhitekture MVC ustrezno prilagoditi njegov pogled.

V nadaljevanju TextObserver seznam, obvestiti() metoda najprej preveri, ali je opazovalec, ki je napovedal posodobitev, opazovalec, ki ga opazuje ta opazovalec. Če je, nato prebere stanje opaznega in natisne novo vrednost.

Seznam 2. TextObserver

 uvoz java.util.Observer; uvoz java.util.Observable; javni razred TextObserver izvaja Observer {private ObservableValue ov = null; javni TextObserver (ObservableValue ov) {this.ov = ov; } posodobitev javne praznine (Observable obs, Object obj) {if (obs == ov) {System.out.println (ov.getValue ()); }}} 

Povežite oba skupaj

Program opazovani objekt obvesti, da želi opazovalec biti obveščen o spremembah njegovega stanja, tako da pokliče opazovani objekt addObserver () metoda. The addObserver () metoda doda opazovalca na notranji seznam opazovalcev, ki jih je treba obvestiti, če se stanje opaznega spremeni.

Spodnji primer, ki prikazuje razred Main, prikazuje, kako uporabljati addObserver () metoda za dodajanje primerka TextObserver razreda (seznam 2) na opazni seznam, ki ga vodi ObservableValue razred (Seznam 1).

Seznam 3. addObserver ()

 javni razred Main {public Main () {ObservableValue ov = new ObservableValue (0); TextObserver do = new TextObserver (ov); ov.addObserver (do); } javna statična void main (String [] args) {Main m = new Main (); }} 

Kako vse skupaj deluje

Naslednje zaporedje dogodkov opisuje, kako običajno pride do interakcije med opazovalcem in opazovalcem v programu.

  1. Najprej uporabnik manipulira s komponento uporabniškega vmesnika, ki predstavlja krmilnik. Krmilnik spremeni model s pomočjo javne metode dostopa - kar je setValue () v zgornjem primeru.
  2. Javna metoda dostopa spremeni zasebne podatke, prilagodi notranje stanje modela in ga pokliče setChanged () metoda, ki označuje, da se je stanje spremenilo. Nato pokliče notifyObservers () da opazovalce obvesti, da se je spremenil. Klic k notifyObservers () lahko izvedemo tudi drugje, na primer v posodobitveni zanki, ki se izvaja v drugi niti.
  3. The nadgradnja() Za vsakega opazovalca se pokličejo metode, ki kažejo na spremembo stanja. Opazovalci dostopajo do podatkov modela prek metod javnega dostopa do modela in posodabljajo svoje poglede.

Opazovalec / opazen v arhitekturi MVC

Zdaj pa si oglejmo primer, ki dokazuje, kako opazovalci in opazovalci običajno delujejo skupaj v arhitekturi MVC. Tako kot model v ObservableValue (Seznam 1) model v tem primeru je zelo preprost. Njeno notranje stanje je sestavljeno iz ene celoštevilčne vrednosti. Z državo se manipulira izključno z dostopnimi metodami, kot so tiste v ObservableValue. Koda za model najdete tukaj.

Sprva je bil napisan preprost besedilni pogled / razred krmilnika. Razred združuje značilnosti pogleda (besedilno prikaže vrednost trenutnega stanja modela) in krmilnika (uporabniku omogoča vnos nove vrednosti za stanje modela). Koda je najdena tukaj.

Z načrtovanjem sistema z uporabo arhitekture MVC (namesto da bi v en monolitni razred vdelali kodo modela, pogleda in krmilnika besedila) je sistem enostavno preoblikovan tako, da upravlja drug pogled in drug krmilnik. V tem primeru je bil napisan drsni pogled / razred krmilnika. Položaj drsnika predstavlja vrednost trenutnega stanja modela in ga lahko uporabnik prilagodi tako, da nastavi novo vrednost stanja modela. Koda je najdena tukaj.

O avtorju

Todd Sundsted piše programe, odkar so računalniki na voljo v namiznih modelih. Čeprav je bil Todd prvotno zainteresiran za izdelavo porazdeljenih objektnih aplikacij v jeziku C ++, se je Todd preselil v programski jezik Java, ko je Java postala očitna izbira za takšno stvar.

To zgodbo "Opazovalec in opazljiv" je prvotno objavil JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found