Programování

Pozorovatel a pozorovatel

Zde je problém: Navrhujete program, který bude vykreslovat data popisující trojrozměrnou scénu ve dvou dimenzích. Program musí být modulární a musí umožňovat více současných pohledů na stejnou scénu. Každý pohled musí být schopen zobrazit scénu z jiného výhodného bodu za různých světelných podmínek. Ještě důležitější je, že pokud se změní jakákoli část podkladové scény, musí se pohledy aktualizovat samy.

Žádný z těchto požadavků nepředstavuje nepřekonatelnou programovou výzvu. Pokud musel být napsán kód, který zpracovává každý požadavek de novo, ale přidalo by to k celkovému úsilí významnou práci. Naštěstí podporu těchto úkolů již poskytuje knihovna tříd Java ve formě rozhraní Pozorovatel a třída Pozorovatelný- oba jsou částečně inspirováni požadavky architektury MVC.

Architektura Model / View / Controller (MVC)

Architektura Model / View / Controller byla představena jako součást Smalltalk, populárního objektově orientovaného programovacího jazyka, který vynalezl Alan Kay. MVC byl navržen tak, aby snížil programovací úsilí potřebné k vytvoření systémů využívajících více synchronizovaných prezentací stejných dat. Jeho ústředními charakteristikami je, že s modelem, řadiči a pohledy se zachází jako s oddělenými entitami a že změny provedené v modelu by se měly automaticky projevit v každém z pohledů.

Kromě příkladu programu popsaného v úvodním odstavci výše lze architekturu Model / View / Controller použít pro projekty, jako jsou následující:

  • Balíček grafů, který obsahuje simultánní zobrazení sloupcového, spojnicového a výsečového grafu se stejnými daty.
  • CAD systém, ve kterém lze části návrhu prohlížet v různých zvětšeních, v různých oknech a v různých měřítcích.

Obrázek 1 ilustruje architekturu MVC v její nejobecnější podobě. Existuje jeden model. S modelem manipuluje více řadičů; více pohledů zobrazuje data v modelu a mění se podle změn stavu modelu.

Obrázek 1. Architektura Model / View / Controller

Výhody MVC

Architektura Model / View / Controller má několik výhod:

  • Mezi komponenty programu existuje jasně definované oddělení - problémy v každé doméně lze řešit samostatně.
  • K dispozici je dobře definované API - cokoli, co správně používá API, může nahradit buď model, pohled nebo ovladač.
  • Vazba mezi modelem a pohledem je dynamická - dochází k ní v době běhu, nikoli v době kompilace.

Začleněním architektury MVC do designu mohou být části programu navrženy samostatně (a navrženy tak, aby svou práci zvládly dobře) a poté za běhu spojeny dohromady. Pokud bude komponenta později považována za nevhodnou, může být vyměněna bez ovlivnění ostatních částí. Porovnejte tento scénář s monolitickým přístupem typickým pro mnoho rychlých a špinavých programů Java. Rámec často obsahuje celý stav, zpracovává všechny události, provádí všechny výpočty a zobrazuje výsledek. U všech těchto systémů s výjimkou těch nejjednodušších tedy není provádění změn faktické.

Definování dílů

Model je objekt, který představuje data v programu. Spravuje data a provádí všechny transformace těchto dat. Model nemá žádné konkrétní znalosti o svých řadičích ani o svých pohledech - neobsahuje žádné interní odkazy. Samotný systém spíše přebírá odpovědnost za udržování vazeb mezi modelem a jeho pohledy a upozornění na pohledy, když se model změní.

Pohled je objekt, který spravuje vizuální zobrazení dat představovaných modelem. Produkuje vizuální reprezentaci objektu modelu a zobrazuje data uživateli. Interaguje s modelem prostřednictvím odkazu na samotný objekt modelu.

Ovladač je objekt, který poskytuje prostředky pro interakci uživatele s daty představovanými modelem. Poskytuje prostředky, kterými se provádějí změny, ať už v informacích v modelu, nebo ve vzhledu pohledu. Interaguje s modelem prostřednictvím odkazu na samotný objekt modelu.

V tomto okamžiku může být užitečný konkrétní příklad. Vezměme si jako příklad systém popsaný v úvodu.

Obrázek 2. Trojrozměrný vizualizační systém

Ústředním prvkem systému je model trojrozměrné scény. Model je matematickým popisem vrcholů a ploch, které tvoří scénu. Data popisující každý vrchol nebo tvář mohou být upravena (možná jako výsledek vstupu uživatele nebo algoritmu zkreslení scény nebo morfování). Neexistuje však žádná představa o úhlu pohledu, způsobu zobrazení (drátěný nebo pevný), perspektivě nebo světelném zdroji. Model je čistým znázorněním prvků, které tvoří scénu.

Část programu, která převádí data v modelu na grafické zobrazení, je pohled. Pohled ztělesňuje skutečné zobrazení scény. Jedná se o grafické znázornění scény z určitého úhlu pohledu, za určitých světelných podmínek.

Řadič ví, co lze s modelem udělat, a implementuje uživatelské rozhraní, které umožňuje zahájit tuto akci. V tomto příkladu může ovládací panel pro zadávání dat uživateli umožnit přidávat, upravovat nebo mazat vrcholy a plochy.

Pozorovatel a pozorovatel

Jazyk Java podporuje architekturu MVC dvěma třídami:

  • Pozorovatel: Jakýkoli objekt, který si přeje být upozorněn, když se změní stav jiného objektu.
  • Pozorovatelný: Jakýkoli objekt, jehož stav může být zajímavý a u kterého může jiný objekt zaregistrovat zájem.

Tyto dvě třídy lze použít k implementaci mnohem více než jen k architektuře MVC. Jsou vhodné pro jakýkoli systém, kde je třeba objekty automaticky upozorňovat na změny, ke kterým v jiných objektech dochází.

Typicky je model podtypem Pozorovatelný a pohled je podtypem Pozorovatel. Tyto dvě třídy zpracovávají funkci automatického upozornění MVC. Poskytují mechanismus, kterým mohou být pohledy automaticky upozorňovány na změny v modelu. Odkazy na objekt k modelu v řadiči i v pohledu umožňují přístup k datům v modelu.

Funkce pozorovatel a pozorovatel

Následuje seznam kódů pro pozorovatele a pozorovatelné funkce:

Pozorovatel

  • public void update (Observable obs, Object obj)

    Volá se, když došlo ke změně ve stavu pozorovatelného.

Pozorovatelný

  • public void addObserver (Observer obs)

    Přidá pozorovatele do interního seznamu pozorovatelů.

  • public void deleteObserver (Observer obs)

    Odstraní pozorovatele z interního seznamu pozorovatelů.

  • public void deleteObservers ()

    Odstraní všechny pozorovatele z interního seznamu pozorovatelů.

  • public int countObservers ()

    Vrátí počet pozorovatelů z interního seznamu pozorovatelů.

  • protected void setChanged ()

    Nastaví interní příznak, který označuje, že tento pozorovatelný stav se změnil.

  • protected void clearChanged ()

    Vymaže vnitřní příznak, který označuje, že tento pozorovatelný stav se změnil.

  • public boolean hasChanged ()

    Vrátí booleovskou hodnotu true, pokud tato pozorovatelná změnila stav.

  • public void notifyObservers ()

    Zkontroluje vnitřní příznak, zda pozorovatel změnil stav, a upozorní všechny pozorovatele.

  • public void notifyObservers (objekt obj)

    Zkontroluje vnitřní příznak, zda pozorovatel změnil stav, a upozorní všechny pozorovatele. Předá objekt určený v seznamu parametrů do oznámit() metoda pozorovatele.

Dále se podíváme na to, jak vytvořit nový Pozorovatelný a Pozorovatel třídy a jak je spojit dohromady.

Rozšiřte pozorovatelné

Rozšířením třídy se vytvoří nová třída pozorovatelných objektů Pozorovatelný. Protože třída Pozorovatelný již implementuje všechny metody nezbytné k zajištění požadovaného chování, odvozená třída potřebuje pouze nějaký mechanismus pro úpravu a přístup k vnitřnímu stavu pozorovatelného objektu.

V ObservableValue seznam níže je vnitřní stav modelu zachycen celým číslem n. K této hodnotě se přistupuje (a co je důležitější, upravuje se) pouze prostřednictvím veřejných přístupových objektů. Pokud se hodnota změní, vyvolá pozorovatelný objekt svoji vlastní setChanged () metoda označující, že se změnil stav modelu. Potom vyvolá své vlastní notifyObservers () metoda za účelem aktualizace všech registrovaných pozorovatelů.

Výpis 1. ObservableValue

 import java.util.Observable; public class ObservableValue extends 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; }} 

Implementujte pozorovatele

Implementací se vytvoří nová třída objektů, které sledují změny stavu jiného objektu Pozorovatel rozhraní. The Pozorovatel rozhraní vyžaduje, aby Aktualizace() metoda bude poskytována v nové třídě. The Aktualizace() metoda je volána kdykoli pozorovatelná změní stav a oznamuje tuto skutečnost voláním jejího notifyObservers () metoda. Pozorovatel by pak měl vyslechnout pozorovatelný objekt, aby určil jeho nový stav, a v případě architektury MVC vhodně upravit jeho pohled.

V následujícím TextObserver výpis, oznámit() metoda nejprve zkontroluje, zda pozorovatel, který ohlásil aktualizaci, je pozorovatelný, který tento pozorovatel pozoruje. Pokud je, přečte stav pozorovatelného a vytiskne novou hodnotu.

Výpis 2. TextObserver

 import java.util.Observer; import java.util.Observable; veřejná třída TextObserver implementuje Observer {private ObservableValue ov = null; public TextObserver (ObservableValue ov) {this.ov = ov; } public void update (Observable obs, Object obj) {if (obs == ov) {System.out.println (ov.getValue ()); }}} 

Spojte je dohromady

Program upozorní pozorovatelný objekt tím, že si pozorovatel přeje být upozorněn na změny jeho stavu voláním pozorovatelného objektu addObserver () metoda. The addObserver () metoda přidá pozorovatele na interní seznam pozorovatelů, kteří by měli být upozorněni, pokud se změní stav pozorovatelných.

Níže uvedený příklad, ukazující třídu Main, ukazuje, jak používat addObserver () metoda pro přidání instance TextObserver třídy (Výpis 2) na pozorovatelný seznam udržovaný ObservableValue třída (Výpis 1).

Výpis 3. addObserver ()

 public class Main {public Main () {ObservableValue ov = new ObservableValue (0); TextObserver to = new TextObserver (ov); ov.addObserver (do); } public static void main (String [] args) {Main m = new Main (); }} 

Jak to všechno funguje společně

Následující posloupnost událostí popisuje, jak v rámci programu obvykle dochází k interakci mezi pozorovatelem a pozorovatelem.

  1. Nejprve uživatel manipuluje s komponentou uživatelského rozhraní představující řadič. Řadič provede změnu modelu pomocí metody veřejného přístupového objektu - což je setValue () ve výše uvedeném příkladu.
  2. Metoda veřejného přístupového modulu upravuje soukromá data, upravuje vnitřní stav modelu a volá jeho setChanged () metoda označující, že se jeho stav změnil. Pak zavolá notifyObservers () informovat pozorovatele, že se to změnilo. Volání na notifyObservers () lze provést i jinde, například v aktualizační smyčce spuštěné v jiném vlákně.
  3. The Aktualizace() jsou volány metody na každém z pozorovatelů, což naznačuje, že došlo ke změně stavu. Pozorovatelé přistupují k datům modelu prostřednictvím veřejných přístupových metod modelu a aktualizují své příslušné pohledy.

Pozorovatel / pozorovatelný v architektuře MVC

Podívejme se nyní na příklad, který ukazuje, jak pozorovatelé a pozorovatelé obvykle spolupracují v architektuře MVC. Jako model v ObservableValue (Výpis 1) je model v tomto příkladu velmi jednoduchý. Jeho vnitřní stav se skládá z jediné celočíselné hodnoty. Stát je manipulován výhradně pomocí přístupových metod, jako jsou ty v ObservableValue. Kód modelu najdete zde.

Zpočátku byla napsána jednoduchá třída zobrazení textu / řadiče. Třída kombinuje funkce pohledu (textově zobrazuje hodnotu aktuálního stavu modelu) i kontroleru (umožňuje uživateli zadat novou hodnotu pro stav modelu). Kód naleznete zde.

Návrh systému pomocí architektury MVC (spíše než vložení kódu pro model, zobrazení a textový řadič do jedné monolitické třídy) je systém snadno přepracován tak, aby zpracovával jiný pohled a jiný řadič. V tomto případě byla zapsána třída posuvníku / řadiče. Poloha posuvníku představuje hodnotu aktuálního stavu modelu a může ji uživatel upravit tak, aby nastavila novou hodnotu pro stav modelu. Kód naleznete zde.

O autorovi

Todd Sundsted píše programy od doby, kdy byly počítače dostupné v modelech pro stolní počítače. Ačkoli se Todd původně zajímal o vytváření aplikací distribuovaných objektů v C ++, přešel na programovací jazyk Java, když se Java stala jasnou volbou pro tento druh věcí.

Tento příběh „Pozorovatel a pozorovatel“ byl původně publikován společností JavaWorld.

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