Architektonický vzor MVC. Přátelský přístup k vývoji webu: Model MVC

SRC:
O'Reillu. Návrhové vzory jazyka ActionScript 3.0.
Kapitola 12. Model-View-Controller Pattern.


Jaký je vzor Model-View-Controller?

Model-View-Controller (MVC) je složený vzor nebo více vzorů, které spolupracují při implementaci složitých aplikací. Tento vzor se nejčastěji používá k vytváření aplikačních rozhraní a jak název napovídá, skládá se ze tří prvků:

Model(Model)
Obsahuje aplikační data a logiku pro správu stavu této aplikace

Výkon(Pohled)
Implementuje uživatelské rozhraní a stav aplikace viditelné na obrazovce

Ovladač(ovladač)
Zpracovává uživatelské akce, které ovlivňují stav aplikace.

Síla vzoru MVC pochází přímo z oddělení těchto tří prvků, aby se předešlo překrývání odpovědností každého z nich. Podívejme se, za co je každý prvek zodpovědný.

Model

Model je zodpovědný za řízení stavu aplikace. Aplikační logiku v modelu představují dvě důležité úlohy: model odpovídá na požadavky týkající se stavu aplikace a provádí akce v reakci na požadavek na změnu stavu.

Výkon

Pohled je vzhled aplikace. Uživatel komunikuje s aplikací prostřednictvím Zobrazení. Aplikace může obsahovat více pohledů, které mohou být jak vstupním, tak výstupním mechanismem. Například v přenosném digitálním přehrávači, jako je iPod, bude obrazovka zařízení Zobrazit. Tlačítka přehrávače jsou také považována za zobrazení. Na obrazovce se zobrazuje název a délka skladby, obrázek obalu alba a další věci, které korelují s aktuálním stavem zařízení. Pohled nemusí být vidět. V přenosném přehrávači je hudba přehrávaná přes sluchátka zároveň prezentací. Například stisknutí tlačítka může způsobit nějakou zvukovou zpětnou vazbu v podobě cvaknutí ve sluchátkách. Změny hlasitosti se projeví také na výstupním audio kanálu. Zvuková zpětná vazba souvisí se stavem aplikace.

Ovladač

Ačkoli termín Controller implicitně implikuje rozhraní, přes které je aplikace ovládána, ve vzoru MVC Controller neobsahuje žádné prvky uživatelského rozhraní. Jak bylo uvedeno výše, prvky uživatelského rozhraní, které poskytují vstup, patří do komponenty View. Řadič určuje, jak pohledy reagují na vstup uživatele.

Řekněme, že náš digitální přehrávač má tlačítka Hlasitěji A Klid v zobrazení. Hlasitost zvuku je stavová proměnná. Model bude sledovat tuto proměnnou, aby změnil hodnotu této proměnné podle aplikační logiky. Pokud je hodnota hlasitosti zvuku kalibrována od 0 do 10, ovladač určí, o kolik se má zvuk zvýšit nebo snížit, když jedno z těchto tlačítek stisknete jednou. Chování může modelu říci, aby zvýšil hlasitost o 0,5 nebo 0,1 nebo o jakoukoli jinou hodnotu, jak je specifikováno programem. V tomto duchu jsou Controllery specifické implementace, které určují, jak bude aplikace reagovat na vstup uživatele.

Ačkoli každý prvek v triádě MVC má samostatnou a jedinečnou odpovědnost, nefungují izolovaně. Ve skutečnosti, aby bylo možné sestavit vzor MVC, musí každý prvek komunikovat s ostatními. Na to, co to znamená, se podíváme níže.

Interakce prvků MVC

Každý prvek ve vzoru MVC komunikuje s ostatními velmi specifickými způsoby. Komunikace je realizována prostřednictvím sekvence událostí, které jsou obvykle spouštěny interakcí uživatele s aplikací. Posloupnost událostí vypadá takto:

  1. Uživatel interaguje s prvkem uživatelského rozhraní (například kliknutím na tlačítko v zobrazení).
  2. Zobrazení odešle událost kliknutí do řadiče, aby rozhodl, jak s kliknutím naložit.
  3. Ovladač změní model na základě toho, co rozhodl o stisknutí tlačítka.
  4. Model informuje Pohled, že se stav modelu změnil.
  5. Pohled čte informace o stavu v modelu a sám se mutuje.

Toto je velmi jednoduchý diagram interakce prvků MVC. V některých případech může ovladač jednoduše říct, aby se pohled změnil. Toto je jediný případ, kdy se změny pohledu stanou nezbytnými kvůli akcím uživatele a nevyžadují změny v modelu, ale jednoduše vedou pouze k vizuálním změnám. Zamyslete se například nad tím, jak uživatel vybírá skladbu na digitálním přehrávači. Pomocí rolovacích tlačítek vybere skladbu ze seznamu. Zobrazení musí sdělit ovladači, že jsou stisknuta tlačítka pro posun nahoru nebo dolů, ale ovladač nemusí informovat model. Přímo říká View, aby posouval seznam skladeb požadovaným směrem. Tato uživatelská akce nevyžaduje změny modelu. Když však uživatel vybere skladbu ze seznamu a přehraje ji, ovladač změní Model tak, aby odrážel tuto změnu v hodnotě aktuálně přehrávané skladby.

Navíc změny modelu nejsou vždy vyvolány akcemi uživatele. Model se může sám aktualizovat na základě určitých událostí. Vezměte si například ukazatel ceny akcií. Model nesouvisí s aktuální cenou akcií. Samotné náklady se však liší a Model může nastavit časovač pro pravidelné přijímání aktualizovaných dat z webové služby. A poté, kdykoli model aktualizuje svá data o ceně akcií, informuje View, že se stav změnil.

Dalším rysem vzoru MVC je, že každý takový model může mít přiřazeno více než jeden pohled. Například v našem přenosném přehrávači lze nastavení hlasitosti zobrazit na displeji pomocí indikátoru úrovně. A navíc hladina zvuku na audio výstupu koreluje s hlasitostí zvuku ve sluchátkách. Displej i zvuk sluchátek reprezentují stav zařízení.

Podívejte se na obrázek 12-1 a poznamenejte si směr šipek. Ukazují, kdo iniciuje interakce mezi prvky. Aby jeden prvek MVC mohl komunikovat s druhým, musí o něm vědět a mít na tento prvek odkaz.

Představte si Model, View a Controller jako tři různé třídy. Podívejme se, které třídy musí mít odkazy na jiné třídy:

Výkon
Musí mít odkaz na model i ovladač

Ovladač
Potřebuje vlastnit odkaz na Model

Začali jsme konstatováním, že MVC je složený vzor, ​​který kombinuje více vzorů. Možná vás zajímá, jaké šablony jsou součástí této složené šablony. Nebo přesněji, jak je lze zastupovat? Hlavní výhodou použití vzoru MVC je schopnost rozložit jej na tři základní prvky. To nám umožňuje přidružit více pohledů k jednomu modelu a nahradit tak modely a ovladače bez ovlivnění ostatních prvků. Některé prvky v triádě MVC však musí udržovat vazby na jiné prvky a také podporovat aktivní komunikaci mezi nimi. Jak můžeme takové rozdělení nazvat? To se týká vzorů Pozorovatel, Strategie a Kompozit.

Implementace vzorů v MVC

Jak jsme již viděli, model může být spojen s několika pohledy. V MVC musí model informovat všechny s ním spojené pohledy o změnách, ke kterým dojde. Navíc to musí být provedeno bez znalosti konkrétních podrobností o zobrazeních a aniž byste věděli, kolik zobrazení by se mělo změnit. Tohoto úkolu lze nejlépe provést pomocí implementace vzoru Prohlížeč (viz kapitola 8).

Každý model může mít přiřazeno více pohledů. Pohledy mohou být také složité, s více okny nebo panely, které obsahují další prvky uživatelského rozhraní. Například prvky rozhraní, jako jsou tlačítka, textová pole, seznamy, posuvníky atd. lze seskupit do panelu s kartami a panel zase může být součástí okna spolu s dalšími panely. Každé tlačítko nebo skupina tlačítek může být pohledem. Totéž s kolekcí textových polí. Zdá se užitečné zacházet s panelem nebo oknem, které obsahuje kolekce jednoduchých pohledů, stejným způsobem, jakým zacházíme s jakýmikoli jinými pohledy. Zde nám použití vzoru Composer ušetří mnoho úsilí (viz kapitola 6). Proč je implementace vzoru Composer v tomto kontextu tak užitečná? Pokud lze pohledy vnořit, což jsou při vytváření pomocí vzoru Composer, proces aktualizace se zjednoduší. Událost aktualizace automaticky obejde všechna podřízená zobrazení. Vytváření komplexních pohledů je snazší, když není potřeba posílat jednotlivé aktualizační zprávy do každého vnořeného pohledu.

Reprezentace omezují svou činnost pouze na vnější reprezentaci stavu Modelu. Předávají události uživatelského rozhraní řadiči. Řadič je tedy spíše algoritmem, jak zpracovat uživatelský vstup v konkrétním pohledu. Toto delegování zapouzdřuje implementaci toho, jak se určitý prvek uživatelského prvku chová za podmínek změny modelu. Můžeme docela snadno nahradit jeden ovladač za stejný pohled, abychom získali odlišné chování. Toto je ideální kontext pro implementaci šablony strategie.

Příklad minimalistické šablony MVC

Tento jednoduchý příklad sleduje stisknuté klávesy. Když je stisknuto další tlačítko, způsobí to změnu modelu a informuje View o nutnosti aktualizace. Zobrazení používá standardní výstupní okno ve Flashi k umístění znakového kódu, který uživatel zadal. Kód znaku je číselná hodnota znaku v tabulce kódů aktuálního rozvržení. Tento příklad vysvětluje, jak jsou vzory Explorer, Strategy a Composer integrovány do MVC.

Modelujte jako konkrétní předmět v šabloně Observer

Vztah mezi modelem a pohledem je vztah mezi objektem a prohlížečem (viz kapitola 8). Model musí implementovat rozhraní Předmět, které je součástí vzoru Prohlížeč. Naštěstí má ActionScript 3.0 vestavěné třídy, které již tento princip implementují, a používají k informování prohlížečů o změnách model událostí ActionScript.

Třída EventDispatcher v jazyce ActionScript 3.0

Třída EventDispatcher poskytuje rozhraní IEventDispatcher. Spolu s dalšími metodami definuje rozhraní IEventDispatcher následující metody požadované pro předmět v šabloně prohlížeče. (Podrobnosti o všech parametrech metody najdete v dokumentaci AS3.)

addEventListener(type :String , listener:Function , useCapture:Boolean = false , priorita:int = 0 , useWeakReference:Boolean = false ) :void removeEventListener(type :String, listener:Function, useCapture:Boolean:void = false dispatch) event:Event) :Boolean

Aby se model choval jako konkrétní entita ve vzoru Browser, je nutné implementovat rozhraní IEventDispatcher. Nejjednodušší způsob, jak daná vlastní třída získat schopnost distribuovat události, je zdědit od třídy EventDispatcher.

Prohlížeč registruje metody posluchače pro příjem oznámení z objektů EventDispatcher pomocí metody addEventListener().

Model

Náš model ukládá kód znaku odpovídající stisknuté klávese ve vlastnosti. Musíte implementovat setter a getter, abyste umožnili View a Controlleru přistupovat a měnit tuto vlastnost. Pojďme definovat pro náš model (příklad 12-1).

Příklad 12-1. IModel.as

balíček ( import flash.events .* ; veřejné rozhraní IModel rozšiřuje IEventDispatcher ( funkce setKey(key :uint) :void ; funkce getKey() :uint; ) )

Rozhraní IModel, znázorněné v příkladu 12-1, rozšiřuje rozhraní IEventDispatcher a definuje dvojici metod pro čtení a nastavení znakového kódu poslední stisknuté klávesy. Protože rozhraní IModel rozšiřuje IEventDispatcher, každá třída, která jej implementuje, musí implementovat všechny metody definované v obou rozhraních. Třída Model, znázorněná v příkladu 12-2, implementuje rozhraní IModel.

Příklad 12-2. Model.as

package ( import flash.events .* ; model veřejné třídy rozšiřuje EventDispatcher implementuje IModel ( private var lastKeyPressed:uint=0 ; veřejná funkce setKey(key :uint) :void ( this .lastKeyPressed =key ;Even dispatcht(new Event(Event. ZMĚNA ) ) ; // událost se šíří) veřejná funkce getKey() :uint ( return lastKeyPressed; ) ) )

Třída Model rozšiřuje třídu EventDispatcher, která již implementuje rozhraní IEventDispatcher. Všimněte si, že funkce dispatchEvent() se volá uvnitř metody setKey(). Odešle událost CHANGE všem registrovaným prohlížečům, jakmile se změní hodnota lastKeyPressed uvnitř metody setKey().

Controller jako specifická strategie v šabloně strategie.

Vztah mezi kontrolérem a pohledem může být reprezentován jako strategie a kontext ve vzoru strategie. Každý Controller bude specifickou strategií, která implementuje požadované chování v rámci rozhraní strategie.

Ovladač

V našem minimalistickém příkladu je chování vyžadované od Controlleru jednoduše akceptováním události stisku klávesy. IKeyboardInputHandler je rozhraní strategie (příklad 12-3), kde je definována jedna metoda keyPressHandler().

Příklad 12-3. IKeyboardInputHandler.as

balíček ( import flash.events .* ; veřejné rozhraní IKeyboardInputHandler ( funkce keyPressHandler(event:KeyboardEvent) :void ; ) )

Konkrétním Controllerem bude třída Controller (příklad 12-4), která implementuje rozhraní IKeyboardInputHandler.

Příklad 12-4. Controller.as

package ( import flash.events .* ; veřejná třída Controller implementuje IKeyboardInputHandler ( private var model:IModel; public function Controller(aModel:IModel) ( this .model =aModel; ) public function keyPressHandler(event:KeyboardEvent) :void ( model. setKey(event.charCode); // změnit model } } }

Všimněte si, že Controller má konstruktor, který jako parametr bere instanci modelu. To je nezbytné, aby řídicí jednotka mohla komunikovat s modelem, jak je znázorněno na obrázku 12-1. Proto je nutné uložit odkaz na Model.

Metoda keyPressHandler() převezme událost uživatelského rozhraní (v tomto případě KeyboardEvent) jako parametr a poté rozhodne, jak ji zpracovat. V našem příkladu jednoduše nastaví kód stisknuté klávesy v Modelu.

Reprezentace jako konkrétní prohlížeč v šabloně prohlížeče a kontext v šabloně strategie

Pohled je možná nejsložitějším prvkem ve vzoru MVC. Hraje roli integrující části při implementaci vzorů pozorovatele i strategie, což tvoří základ jeho vztahu s modelem a kontrolorem. Třída View, znázorněná v příkladu 12-5, implementuje pohled v minimalistickém příkladu.

Příklad 12-5. Zobrazit.jako

balíček ( import flash.events .* ; import flash.display .* ; public class View ( private var model:IModel; private var controller:IKeyboardInputHandler; public function View(aModel:IModel,oController:IKeyboardInputHandler,target :Stage ) ( toto .model =aModel tento .řadič =oŘídicí; // se přihlásí k odběru upozornění od Modelu model.addEventListener (Event.CHANGE ,tato .aktualizace) ; // se přihlásí k přijímání úhozů ze scény target .addEventListener ( KeyboardEvent . KEY_DOWN , toto . onKeyPress ) ; ) aktualizace soukromé funkce(událost:Událost) :void (// příjem dat z modelu a aktualizace pohledu trace(model.getKey());) soukromá funkce onKeyPress(event:KeyboardEvent) :void (

// zpracování je přeneseno do Controlleru (Strategie) ke zpracování

Kromě kreslení uživatelského rozhraní provádí třída View několik dalších důležitých úkolů. Registruje se u modelu, aby mohl přijímat aktualizační události, a deleguje řízení na zpracování uživatelského vstupu. V našem příkladu pohled nemá žádnou vnější viditelnou přítomnost na scéně, ale zobrazuje stav modelu v okně Výstup. Potřebuje přijmout událost stisku klávesy a zaregistruje metodu onKeyPress() pro příjem události KEY_DOWN ze scény. Druhým úkolem je zaregistrovat metodu listener update() pro příjem události CHANGE z modelu. Po upozornění na změnu metoda update() přečte kód poslední stisknuté klávesy z Modelu a vytiskne jej ve výstupním okně pomocí funkce trace().

Budování MVC triády

Podívali jsme se na implementaci každé ze tří částí vzoru MVC samostatně. Musí však existovat klient, který inicializuje každý prvek a sestaví model MVC. Ve skutečnosti nepůjde o žádnou složitou konstrukci – vše, co je potřeba udělat, bylo již hotové při psaní tříd Model, View a Controller. Příklad 12-6 poskytuje třídu dokumentu Flash, která ilustruje prvky MVC.

Příklad 12-6. Main.as (hlavní třída minimalistického příkladu)

balíček ( import flash.display .* ; import flash.events .* ; /** * Hlavní třída * @ účel: Třída dokumentu pro film */ public class Main rozšiřuje Sprite ( public function Main() ( var model:IModel=new Model ; var controller:IKeyboardInputHandler=new Controller(model) ; var view:View=new View(model,controller,this .stage ) ; ) ) )

Jakmile jsou model, ovladač a pohled inicializovány, budou spolu komunikovat a začnou pracovat. Stisknutím klávesy na klávesnici se v okně Výstup zobrazí kód odpovídajícího znaku.

Musíte zakázat zkratky pro testování stisku kláves. Jinak uživatelské rozhraní Flash zachytí události stisku kláves, které odpovídají zkratkám. Chcete-li zkratky deaktivovat, vyberte možnost Deaktivovat klávesové zkratky z nabídky Ovládání, když je film spuštěn.

Všimněte si, že instance modelu je předána řadiči. Podobně jsou instance Model a Controller předány do View. Stávající Model a Controller můžeme jednoduše nahradit jinými, pokud implementují rozhraní IModel a IKeyboardInputHandler. Další pohledy lze také bezbolestně přidat přímo do vztahu Subject-Viewer mezi Model a View. Model neví nic o zobrazeních, protože úkolem zobrazení je zaregistrovat se jako posluchač pro oznámení o změně modelu. To je velké plus vzoru MVC; Model, View a Controller jsou oddělené a volně spojené, což poskytuje flexibilitu při jejich použití.

Vnořené pohledy a uzly šablony Composer

Jak si možná vzpomínáte, View je možná nejsložitějším prvkem v triádě MVC, protože v kontextu MVC se podílí jak na implementaci vzoru Viewer, tak na strategii. Naše prvky View mohou být složitější, protože mohou implementovat třetí vzor, ​​Composer (viz příklady vzoru Composer v kapitole 6). Implementace pohledů jako prvků šablony Composer vám umožňuje pracovat se složitými uživatelskými rozhraními, která obsahují více pohledů. Vnoření pohledů přináší do procesu aktualizace uživatelského rozhraní určité výhody, protože aktualizace lze šířit podél větví stromu struktury složeného pohledu. Kompozitní pohledy mohou také přidávat a odstraňovat vnořené pohledy na základě chování aplikace a uživatelských preferencí. Dobrým příkladem komplexního rozhraní je panel Properties Inspector ve vývojovém prostředí Flash. Obsah Inspektoru vlastností je závislý na kontextu a prvky uživatelského rozhraní se objevují a mizí v závislosti na tom, jaký objekt je ve scéně vybrán.

Komponentní a složený pohled

Prvním krokem je vytvoření komponenty a složených tříd pro pohled. Tyto třídy musí být deklarovány jako abstraktní, musí být podtřídy a nesmí vytvářet instance instancí, jak ukazuje příklad 12-7.

Příklad 12-7. ComponentView.as

balíček ( import flash.errors .IllegalOperationError ; import flash.events .Event ; import flash.display .Sprite ; veřejná třída ComponentView rozšiřuje Sprite ( ( protected var model:Object ; protected var controller:Object ; veřejná funkce ComponentView(aModel:Object , aController:Object =null ) ( this .model =aModel; this .controller =aController; ) public function add (c:ComponentView) :void ( throw new IllegalOperationError("operace přidání není podporována" ) ; ) public function remove(c: ComponentView) :void ( vyvolá novou chybu IllegalOperationError( "operace odstranění není podporována"); ) veřejná funkce getChild(n:int ) :ComponentView ( vyvolá nové IllegalOperationError("Operace getChild není podporována" ); return null;

)

// metoda ABSTRACT (musí být přepsána v podřízené třídě)

aktualizace veřejné funkce(event:Event=null) :void ())))

Třída ComponentView z příkladu 12-7 definuje abstraktní rozhraní pro Component View. To je podobné klasické třídě komponent z kapitoly 6, ale s několika klíčovými rozdíly. Třída ComponentView ukládá odkaz na model a pohled a obsahuje konstruktor. Ne všechny pohledy zpracovávají uživatelský vstup a pohled komponenty lze zkonstruovat pouhým předáním instance modelu. Proto parametr aController má v konstruktoru ve výchozím nastavení hodnotu null. Všimněte si také, že třída ComponentView je zděděna ze třídy Sprite. To dává smysl, protože většina pohledů kreslí uživatelské rozhraní na scéně. Vlastnosti a metody implementované ve třídě Sprite můžeme použít ke kreslení a přidávání objektů do seznamu zobrazení.

Metoda update() by se měla chovat jako abstraktní metoda. Podřízené pohledy, které jsou potomky ComponentView, musí přepsat a implementovat metodu update(), aby mohly aktualizovat svou část uživatelského rozhraní. Z tohoto důvodu je metodě předán parametr typu Event. Tento parametr je také standardně nastaven na null, což umožňuje volání update() bez předání události jako parametru. Tento přístup je užitečný, když je původně vykreslené uživatelské rozhraní ve výchozím stavu a náš další příklad to ilustruje. // třída ABSTRACT (musíte z ní dědit, aniž byste vytvořili instanci této třídy) public class CompositeView rozšiřuje ComponentView ( private var aChildren:Array ; veřejná funkce CompositeView(aModel:Object ,aController:Object =null ) ( super (aModel,aController) ; toto .aChildren =new Array ; ) přepíše veřejnou funkci add (c:ComponentView ) :void ( aChildren.push (c) ; ) přepíše aktualizaci veřejné funkce (event:Event=null ) :void ( pro každou (var c:ComponentView v aChildren) ( c.update (událost) ; ) ) )

Všimněte si přepisovací funkce update() třídy CompositeView v příkladu 12-8. Volá metodu aktualizace u všech podřízených tříd. Volání funkce update() v kořenu struktury složeného pohledu tedy rozšíří aktualizaci do celé struktury a projde strom komponenty a aktualizuje všechny pohledy. Pojďme rozšířit třídy CompositeView a ComponentView a vytvořit strukturu View, abychom viděli, jak to funguje

Pojem MVC (Model-View-Controller) je v posledních letech ve světě webového programování zmiňován velmi často. Každý, kdo je nějakým způsobem spojen s vývojem webových aplikací, se s touto zkratkou tak či onak setkal. Dnes pochopíme, co je koncept MVC a proč se stal populárním.

Dávná historie

MVC není projektový vzor, ​​je to návrhový vzor, ​​který popisuje, jak vytvořit strukturu naší aplikace, odpovědnosti a interakci každé z částí v této struktuře.

Poprvé byl popsán v roce 1979, samozřejmě pro jiné prostředí. Tehdy ještě neexistoval koncept webové aplikace. Tim Berners Lee zasel semena World Wide Web (WWW) na počátku devadesátých let a navždy změnil svět. Šablona, ​​kterou dnes používáme, je adaptací původní šablony pro vývoj webu.

Divoká popularita této struktury ve webových aplikacích je způsobena jejím zahrnutím do dvou vývojových prostředí, která se stala velmi populární: Struts a Ruby on Rails. Tato dvě vývojová prostředí určují cestu pro stovky vývojových prostředí, která byla vytvořena později.

MVC pro webové aplikace

Myšlenka návrhového vzoru MVC je velmi jednoduchá: musíme jasně oddělit odpovědnosti za různé funkce v našich aplikacích:

Aplikace je rozdělena do tří hlavních komponent, z nichž každá má na starosti jiné úkoly. Podívejme se na komponenty podrobně na příkladu.

Ovladač

Ovladač spravuje požadavky uživatelů (přijaté jako požadavky HTTP GET nebo POST, když uživatel klikne na prvky rozhraní za účelem provádění různých akcí). Jeho hlavní funkcí je volat a koordinovat akci nezbytných zdrojů a objektů potřebných k provádění akcí specifikovaných uživatelem. Řadič obvykle zavolá vhodný model pro danou úlohu a vybere vhodný pohled.

Model

Model- Jedná se o data a pravidla, která se používají pro práci s daty, která představují koncept správy aplikace. V jakékoli aplikaci je celá struktura modelována jako data, která jsou zpracována určitým způsobem. Co je uživatel pro aplikaci – zpráva nebo kniha? Pouze údaje, které musí být zpracovány podle pravidel (datum nesmí ukazovat do budoucnosti, email musí být v určitém formátu, jméno nesmí být delší než X znaků atd.).

Model poskytuje ovladači reprezentaci dat, která uživatel požadoval (zpráva, stránka knihy, fotoalbum atd.). Datový model bude stejný bez ohledu na to, jak jej chceme uživateli prezentovat. Pro zobrazení dat tedy vybereme jakýkoli dostupný pohled.

Model obsahuje nejdůležitější část logiky naší aplikace, logiku, která řeší problém, se kterým se potýkáme (fórum, obchod, banka atd.). Controller obsahuje v podstatě organizační logiku pro samotnou aplikaci (podobně jako úklid).

Pohled

Pohled poskytuje různé způsoby reprezentace dat získaných z modelu. Může to být šablona, ​​která je vyplněna daty. Může existovat několik různých typů a ovladač si vybere, který z nich je pro aktuální situaci nejvhodnější.

Webová aplikace se obvykle skládá ze sady ovladačů, modelů a pohledů. Ovladač může být navržen jako hlavní ovladač, který přijímá všechny požadavky a volá další ovladače, aby provedly akce v závislosti na situaci.

Podívejme se na příklad

Řekněme, že potřebujeme vytvořit internetové knihkupectví. Uživatel může provádět následující akce: prohlížet knihy, registrovat se, nakupovat, přidávat položky do aktuální objednávky, vytvářet nebo mazat knihy (pokud je správcem). Podívejme se, co se stane, když uživatel klikne na kategorii fantazie k zobrazení názvů knih, které jsou k dispozici v našem obchodě.

Máme specifický ovladač, který zvládne všechny akce související s knihami (zobrazit, upravit, vytvořit atd.). Nazvěme to books_controller.php v našem příkladu. Také potřebujeme model jako model_knihy.php, který zpracovává data a logiku spojenou s položkou obchodu. Na závěr potřebujeme několik pohledů, které reprezentují data, jako je seznam knih, editační stránka a tak dále.

Následující obrázek ukazuje, jak je zpracováván požadavek uživatele na zobrazení seznamu knih na dané téma fantazie:

Řadič (books_controller.php) přijme požadavek uživatele (HTTP GET nebo POST požadavek). Můžeme vytvořit centrální kontrolér, například index.php, který přijme požadavek a zavolá books_controller.php.

Kontrolér zkontroluje požadavek a parametry a poté zavolá model(book_model.php), ptát se má seznam dostupných knih na toto téma fantazie .

Model získá data z databáze (nebo jiného zdroje, který uchovává informace), použije filtry a nezbytnou logiku a poté vrátí data, která představují seznam knih.

Správce používá vhodný pohled k prezentaci dat uživateli. Pokud požadavek pochází z mobilního telefonu, použije se zobrazení mobilního telefonu; pokud uživatel používá určitý design rozhraní, vybere se odpovídající pohled a tak dále.

Jaké jsou výhody?

Nejviditelnější výhodou, kterou získáváme z používání konceptu MVC, je jasné oddělení prezentační logiky (uživatelského rozhraní) a aplikační logiky.

Podpora různých typů uživatelů, kteří používají různé typy zařízení, je v dnešní době běžnou výzvou. Poskytnuté rozhraní by se mělo lišit, pokud požadavek pochází z osobního počítače nebo z mobilního telefonu. Model vrací stejná data, jediný rozdíl je v tom, že regulátor volí pro výstup dat různé pohledy.

Kromě izolace pohledů od aplikační logiky koncept MVC výrazně snižuje složitost velkých aplikací. Kód je mnohem strukturovanější, což usnadňuje údržbu, testování a opětovné použití řešení.

Proč používat pracovní stůl?

Když použijete pracovní plochu, základní struktura MVC je již připravena a vše, co musíte udělat, je rozšířit strukturu umístěním souborů do příslušných adresářů, aby odpovídaly vzoru MVC. Navíc budete mít sadu funkcí, které jsou již napsané a dobře otestované.

Podívejme se na cakePHP jako příklad pracovního stolu MVC. Po instalaci budete mít tři hlavní adresáře:

  • dort/
  • prodejci/

Složka aplikace je místo, kde jsou umístěny vaše soubory. Toto je místo pro vývoj vaší části aplikace.

Ve složce dort jsou hostovány soubory cakePHP (funkce pracovní plochy).

Složka prodejci slouží k ukládání PHP knihoven třetích stran.

Váš pracovní prostor (adresář aplikace) má následující strukturu:

  • aplikace/
    • config/
    • ovladače/
    • locale/
    • modely/
    • pluginy/
    • testy/
    • prodejci/
    • zhlédnutí/
    • webroot/

Musíte umístit své ovladače do adresáře ovladače, modely v adresáři modely a zadejte do adresáře pohledy!

Jakmile začnete používat pracovní plochu, bude okamžitě jasné, kde se nachází téměř každá část vaší aplikace, kterou je třeba vytvořit nebo upravit. Tato organizace sama o sobě značně zjednodušuje proces vývoje a údržby aplikace.

Použití pracovního stolu pro náš příklad

Vzhledem k tomu, že tento tutoriál nemá za cíl ukázat proces vytváření aplikace pomocí cakePHP, ukážeme pouze kód pro model, řadič a pohled s komentáři o výhodách používání MVC workbenche. Kód je záměrně zjednodušený a nevhodný pro použití v reálné aplikaci.

Pamatujte, že jsme se dívali do knihkupectví a zvědavého uživatele, který chtěl vidět kompletní seznam knih na toto téma fantazie. Správce přijal požadavek uživatele a koordinoval potřebné akce.

Jakmile tedy uživatel klikne na tlačítko, prohlížeč si vyžádá danou adresu URL:

www.ourstore.com/books/list/fantasy

CakePHP formátuje URL pomocí vzoru /controller/action/param1/param2, Kde akce je funkce, kterou volá ovladač. Ve staré klasické podobě bude adresa URL vypadat takto:

www.ourstore.com/books_controller.php?action=list&category=fantasy

Ovladač

V pracovním prostředí cakePHP bude náš ovladač vypadat takto:

třída BooksController rozšiřuje AppController (

Seznam funkcí($category) (

$this->set("knihy", $this->Book->findAllByCategory($category));

Funkce add() ( ... ... )

Funkce delete() ( ... ... )

... ... } ?>

Jednoduché, že? Tento ovladač bude uložen jako books_controller.php a zveřejněno v /app/controllers. Obsahuje seznam funkcí, které provádějí akce pro náš příklad, a také další funkce pro provádění operací souvisejících s knihou (přidat novou knihu, odstranit knihu atd.).

Pracovní prostředí nám poskytuje mnoho hotových řešení a stačí si vytvořit seznam knih. Existuje základní třída, která již definuje základní funkčnost řadiče, takže musíte zdědit vlastnosti a funkce této třídy ( AppController je dědicem Ovladač).

Vše, co musíte udělat v seznamu akcí, je zavolat model, abyste získali data, a poté vybrat pohled, abyste je prezentovali uživateli. Zde je návod, jak se to dělá.

tato->Kniha- toto je náš model a část kódu:

$this->Book->findAllByCategory($category)

řekne modelu, aby vrátil seznam knih na vybrané téma (na model se podíváme později).

Metoda soubor v řádku:

$this->set("knihy", $this->Book->findAllByCategory($category));

Řadič předává data do pohledu. Variabilní knihy přijímá data vrácená modelem a zpřístupňuje je pohledu.

Nyní zbývá pouze zobrazit pohled, ale tato funkce se v cakePHP provádí automaticky, pokud použijeme výchozí pohled. Pokud chceme použít jiný typ, musíme metodu explicitně zavolat vykreslit.

Model

Model je ještě jednodušší:

class Book rozšiřuje AppModel (

Proč je prázdný? Protože dědí ze základní třídy, která poskytuje požadovanou funkcionalitu, a my potřebujeme použít konvenci pojmenování CakePHP, aby runtime zvládlo všechny ostatní úlohy automaticky. Například cakePHP podle svého názvu ví, že se tento model používá BooksController a že má přístup k databázové tabulce s názvem knihy.

S touto definicí budeme mít model, který může pouze číst, mazat nebo ukládat data v databázi.

Uložte kód jako book.php ve složce /app/models.

Pohled

Vše, co nyní musíme udělat, je vytvořit pohled (alespoň jeden) pro seznam akcí. Pohled bude obsahovat kód HTML a několik (co nejméně) řádků kódu PHP pro procházení polem knih, které model poskytuje.












Jméno Autor Cena

Jak vidíte, pohled nevytváří celou stránku, ale pouze fragment HTML (v tomto případě tabulku). Protože CakePHP poskytuje jiný způsob, jak definovat šablonu stránky, a pohled je vložen do této šablony. Workbench nám také poskytuje některé pomocné objekty pro provádění běžných úkolů při vytváření částí HTML stránky (vkládání formulářů, odkazů, Ajax nebo JavaScript).

Uložit pohled jako seznam.ctp(seznam je název akce a ctp znamená šablonu CakePHP) ve složce /app/views/books(protože je to pohled pro akci ovladače).

Takto jsou všechny tři komponenty prováděny pomocí CakePHP workbench!

Co je MVC?

MVC je tedy o uživatelském rozhraní (UI). Ne nutně grafické, hlasové ovládání je také dobré. Nezapomínejme, že program nemusí mít uživatelské rozhraní, může mít rozhraní pro programování aplikací (API) nebo nemusí mít vůbec žádné a přesto může být užitečné.

Ale pokud máme uživatele, pak musí existovat uživatelské rozhraní. Co je rozhraní? Toto je souvislá hranice mezi dvěma systémy. V našem případě: na jedné straně - program, na druhé straně - uživatel. Tady jsou.

Program je zcela abstraktní, libovolný předmětový kód. Může dělat něco užitečného a uživatel má potřeby, které lze s pomocí tohoto programu uspokojit. Pak se objeví kousky logiky, které „umí“, jak pomocí tohoto programu dělat přímo to, co uživatel chce. Skladby nejsou v programu předmětově specifické, předmětově specifické logice. Jsou relevantnější pro uživatele s jeho specifickými potřebami a jsou kombinací volání a volání programu.

Případy použití

Jako příklad si představte terminál pro obchodování na burze. Uživatel terminálu podá žádost, ve které uvede, že chce koupit 20 akcií společnosti Svetly Put za cenu 1 500 rublů za akcii. Uvádí také, že aplikace je platná čtyři hodiny a z kterého z jeho účtů budou v případě úspěšné transakce odepsány peníze.

Hmatatelné množství atributů. Uběhne nějaký čas a on si uvědomí, že za tuto cenu nebude moci nakupovat a je připraven zvýšit cenu na 1 550 rublů a ponechat všechny ostatní hodnoty. Poté vybere tuto aplikaci, klikne na tlačítko „změnit“, označí novou cenu, ano. Je to pohodlné.

Ale na burze nemůžete změnit objednávku v předmětové oblasti žádný takový koncept neexistuje. Přihlášku lze pouze podat a zrušit. Chcete-li dát uživateli možnost změnit objednávku jedním kliknutím, musíte si zapamatovat staré hodnoty, odebrat objednávku, nechat je upravit, co si zapamatoval, a zadat novou objednávku. Taková kombinace. Ale pro uživatele to vypadá jako jedna jednoduchá akce: změna aplikace. Tomu se říká případ použití.

Doplňme náš diagram prostorem pro případy použití.

Uživatel by měl mít také možnost vytáhnout tyto případy použití a získat výsledky. Mohou to být tlačítka a další grafické vstupně/výstupní prvky, gesta, rozpoznávání řeči a syntéza. Jakákoli možnost pro výměnu dat a příkazů. Voila:

Uživatel vytáhne jeden z případů použití, který zase manipuluje s programem. Program zveřejní výsledek nebo změny v jeho stavu.

Tak kde je vlastně MVC?

Zbývá jen dát výsledným komponentům známá jména.

Když modelka zveřejňuje změny, je jí jedno pro koho, o View nic neví. Místo nebo společně s View může být na druhém konci jiný subsystém.

Nyní pár detailů.

Jednalo se o klasickou verzi MVC – Active Model. Stává se také, že model neinformuje o změnách. Poté tuto odpovědnost přebírá správce. Ví, jaké manipulace s modelem provádí, a samozřejmě ví, jaké změny stavu modelu mohou následovat. Toto je pasivní model.

A ještě jedna věc. Rozdělení kódu na předmětový a nepředmětový je libovolné a závisí na tom, jak pedantně chceme předmětnou oblast modelovat. Někdy je racionální rozhodnutí zahrnout do modelu nějaký případ použití. Možná to celkově sníží množství kódu a zjednoduší ho.

Za materiál děkujeme našemu předplatiteli Stanislavu Iljičevovi

V tomto článku napíšeme „rámec“ našeho projektu. Termínem „framework“ mám na mysli pracovní kód, který bude založen na přístupu MVC, to znamená, že bude mít jasné rozdělení logiky na ovladače, akce, šablony (pohledy) a modely.

A tak začneme, jak jsem již psal v předchozím článku, vzor MVC implikuje jeden vstupní bod - index.php, všechny požadavky projdou tímto skriptem, bude přes něj fungovat veškerá logika projektu. Pro implementaci tohoto přístupu je nutné nakonfigurovat server, předpokládá se, že web běží na serveru Apache, takže nám stačí vytvořit soubor .htaccess, ve kterém zadáme pravidla směrování URL. Kromě určení vstupního bodu vám směrování umožňuje vytvářet CNC (lidsky čitelné adresy URL). To znamená, že po správné konfiguraci budou adresy stránek vypadat takto: site.ru/article/new.
Nejprve si vytvoříme .htaccess, který přesměruje zpracování všech stránek na skript index.php. Kód vypadá takto:

RewriteEngine na RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule ^(.*)$ index.php?route=$1

Soubor .htaccess musí být umístěn v kořenové složce webu a musíte okamžitě vytvořit skript index.php, který je vstupním bodem. Zapišme jeden řádek do index.php, abychom otestovali přesměrování:

Echo "test";

Nyní můžete zkontrolovat přesměrování, zadat libovolnou adresu a zjistit, co se stane: test-mvc.web/sdf/sdf/ nebo test-mvc.web/sdf/sdf/2342/v žádném případě na tom nezáleží, “ Test ". Pokud jste viděli tento nápis, znamená to, že jsme uspěli.
Pokračujme, pro pohodlí si v rootu webu vytvoříme soubor config.php, ve kterém nastavíme různé konstanty, které usnadní konfiguraci webu. Mohou to být různé cesty ke skriptům, databázové přístupy a tak dále. Nyní v konfiguraci nastavíme následující:

// Nastavte konstanty: define ("DS", DIRECTORY_SEPARATOR); // oddělovač pro cesty k souboru $sitePath = realpath(dirname(__FILE__) . DS); define("SITE_PATH", $sitePath); // cesta ke kořenové složce webu // pro připojení k databázi define("DB_USER", "root"); define("DB_PASS", ""); define("DB_HOST", "localhost"); define("DB_NAME", "blog_mvc");

Abychom mohli používat konstanty a další konfigurační data v celém projektu, musíme do souboru index.php zahrnout skript config.php.
Kromě připojení souboru nastavení je v index.php potřeba vytvořit připojení k databázi, propojit skript s jádrem webu a spustit router, ve kterém bude směrování probíhat.
Nyní, v pořádku, vytvoření připojení k databázi bude v index.php, takže připojení bude otevřeno pouze jednou. Jakmile otevřeme připojení, můžeme jej použít ve všech ovladačích a modelech, ale o tom později. Nyní už jen vytvoříme připojení k databázi. Pro práci s databází jsem se rozhodl použít PDO. Můžete si přečíst více o PDO.
Jádro webu umístíme do složky core a zavoláme skript core.php, zde napíšeme funkci, která se sama připojí, pro její fungování jsou nutné třídy. Tato funkce nám výrazně usnadní a zjednoduší práci s ovladači, modely atp. Protože při pohledu dopředu řeknu, že každý ovladač a každý model bude představovat samostatnou třídu.
Kromě automatického propojování tříd přidáme k jádru vytvoření úložiště (registru), do kterého budeme ukládat všechny potřebné objekty a proměnné, které se mohou kdekoli v projektu hodit.
Také připojíme router v indexovém souboru, analyzuje URL a připojí potřebný ovladač a akci. O tom, co je ovladač, jsem psal v předchozím článku a záměrně jsem vynechal informace o akci, aniž bych je zatěžoval zbytečnými informacemi. Co je tedy akce?
Controller je třída, která obsahuje různé metody s přístupem MVC, každá metoda bude akcí. To znamená, že akce je metoda třídy, která zpracuje data a přenese je do pohledu (šablony). Možná to ještě není úplně jasné, ale po příkladu vše zapadne.
V této fázi stačí teorie, přejděme k praxi. Uvedu kód souborů, jejichž fungování jsem popsal výše.
Kód skriptu Index.php:

// povolení zobrazení všech chyb error_reporting (E_ALL); // připojení konfigurace include ("/config.php"); // Připojení k databázi $dbObject = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS); // připojení jádra webu include (SITE_PATH . DS . "core" . DS . "core.php"); // Načtení routeru $router = new Router($registry); // zápis dat do registru $registry->set ("router", $router); // nastaví cestu ke složce controllers. $router->setPath(SITE_PATH . "řadiče"); //spuštění routeru $router->start();

Skript Core.php:

// Načítání tříd za běhu funkce __autoload($className) ( $filename = strtolower($className) . ".php"; // definujte třídu a najděte k ní cestu $expArr = explode("_", $className ) ; if(empty($expArr) OR $expArr == "Základ")( $složka = "třídy"; )else( switch(strtolower($expArr))( case "controller": $folder = "controllers"; break ; case "model": $složka = "modely"; výchozí: $složka; false ) // zahrnout soubor do třídy include ($file ) // spuštění registru (úložiště) $registry = new Registry;

Třída úložiště Registry.php bude umístěna ve složce /classes/

// Třída úložiště Registr třídy ( private $vars = array(); // sada funkcí záznamu dat ($key, $var) ( if (isset($this->vars[$key]) == true) ( ​​​​throw new Exception("Nelze nastavit var `" . $klíč . "`. Již nastaveno." ) $this->vars[$key] = $var return true; if (isset($this->vars[$key]) == false) ( return null; ) return $this->vars[$key] ) // odstranění datové funkce remove($var) ( unset($ this ->vars[$key]);

Kód souboru router.php, který se nachází ve složce /classes/

// třída routeru Třída Router ( private $registry; private $path; private $args = array(); // získání funkce úložiště __construct($registry) ( $this->registry = $registry; ) // nastavení cesty do složky s ovladači funkce setPath($cesta) ( $cesta = trim($cesta, "/\\"); $cesta .= DS; // pokud cesta neexistuje, signalizujte ji, pokud (is_dir($cesta ) == false ) ( vyvolá novou výjimku ("Neplatná cesta řadiče: `" . $cesta . "`"); ) $this->cesta = $cesta ) // definování řadiče a akce ze soukromé funkce URL getController( &$file, & $controller, &$action, &$args) ( $route = (empty($_GET["route"])) ? "" : $_GET["route"]; unset($_GET[" route"]); if (empty($route)) ( $route = "index"; ) // Získání částí URL $route = trim($route, "/\\"); $parts = explode(" /", $route); // Najděte řadič $cmd_path = $this->path; foreach ($parts jako $part) ( $fullpath = $cmd_path . $part; // Zkontrolujte, zda složka existuje, pokud (is_dir( $fullpath)) ( $cmd_path .= $ část . DS; array_shift($parts);

pokračovat; ) // Najděte soubor if (is_file($fullpath . ".php")) ( $controller = $part; array_shift($parts); break; ) ) // pokud URL neuvádí řadič, pak použijte default index if (empty ($controller)) ( $controller = "index"; ) // Získání akce $action = array_shift($parts);
if (empty($action)) ( $action = "index"; ) $file = $cmd_path . $controller. ".php";

// třída ovladače Controller_Index rozšiřuje Controller_Base ( // šablona public $layouts = "first_layouts"; // akční funkce index() ( $model = new Model_Users(); $userInfo = $model->getUser(); $this-> template->vars("userInfo", $userInfo $this->template->view("index" ));

Pro zobrazení (/views/index/index.php)

Testovací pohled
id:
jméno:

A model:

// třída modelu Model_Users( veřejná funkce getUser())( return array("id"=>1, "name"=>"test_name"); ) )

Jak jste si možná všimli, třída controller dědí z rodičovské třídy Controller_Base. To se provádí za účelem zjednodušení třídy regulátoru. Vzhledem k tomu, že stále potřebujeme propojit třídu pro práci se šablonami, je její připojení umístěno v Controller_Base.
Dám jeho kód, je umístěn ve složce /classes/ a jmenuje se controller_base.php:

// abstraktní třída řadiče Abstract Class Controller_Base ( chráněný $registr; chráněný $šablona; chráněný $layouts; // veřejná šablona $vars = array(); // připojení šablon ve funkci konstruktoru __construct($registry) ( $this-> registry = $registry // šablony $this->template = new Template($this->layouts, get_class($this));

Teď už zbývá jen vymyslet šablony. V abstraktní třídě Controller_Base zavoláme třídu Template a předáme jí název šablony a název kontroleru.
Kód pro třídu Template, která se nachází zde /classes/ a jmenuje se template.php

// třída pro připojení šablon a předávání dat do šablony třídy zobrazení ( private $template; private $controller; private $layouts; private $vars = array(); funkce __construct($layouts, $controllerName) ( $this->layouts = $layouts; ( $this->vars[$varname]) == true) (nespouštěcí_chyba ("Nelze nastavit var `" . $varname . "`. Již nastaveno a přepis není povolen.", E_USER_NOTICE); return false; ) $this ->vars[$varname] = $value return true ) // zobrazení funkce view($name) ( $pathLayout = SITE_PATH . "views" . DS . "layouts" . DS . $this->layouts; ". php"; $obsah_PATH . " . $ this->layouts . "` neexistuje.", E_USER_NOTICE); návrat false; if (file_exists($contentPage) == false) ( trigger_error ("Šablona `" . $jméno . "` neexistuje.", E_USER_NOTICE);

vrátit false;
) foreach ($this->vars as $key => $value) ( ​​​​$$key = $value; ) include ($pathLayout);

))

Pokud jste si pozorně přečetli kód, pravděpodobně vám došlo, že pro zobrazení na stránkách používáme šablonu first_layouts a view (zobrazení) index.php - jeho kód jsem dal o něco výše. Zbývá nám pouze vytvořit soubor šablony first_layouts. Umístíme jej do složky /views/layouts/first_layouts.php

Šablona bude obsahovat následující kód:
záhlaví

Dobré odpoledne, vážení kolegové. V tomto článku bych chtěl mluvit o svém analytickém chápání rozdílů mezi vzory MVC, MVP a MVVM. K napsání tohoto článku mě přivedla touha porozumět moderním přístupům k vývoji velkého softwaru a odpovídajícím architektonickým prvkům. V současné fázi mého kariérního žebříčku nejsem přímým vývojářem, takže článek může obsahovat chyby, nepřesnosti a nedorozumění. Zajímá vás, jak analytici vidí, co dělají programátoři a architekti? Pak vítejte u kočky.

Odkazy
První věcí, kterou bych rád začal, jsou odkazy na externí materiály, které mě vedly při psaní tohoto článku:
Zavedení
V době, kdy slunce svítilo jasněji a tráva byla zelenější, vyvinul tým studentů, jako je autor tohoto článku, software napsáním stovek řádků kódu přímo do rozhraní produktu. Někdy byly pro práci s daty použity služby a manažeři a poté bylo řešení získáno pomocí vzoru Document-View. Podpora takového kódu vyžadovala enormní náklady, protože nový vývojář musel být vyškolen (řeknut), jaký kód je v produktu za co zodpovědný, a o nějakém testování jednotek se nemluvilo. Vývojový tým tvoří 4 lidé, kteří sedí v jedné místnosti.
Čas plynul, práce se změnila. Vyvíjené aplikace se staly většími a složitějšími a z jednoho soudržného týmu vývojářů vzniklo mnoho různých týmů vývojářů, architektů, specialistů na použitelnost, designérů a PM. Nyní je každý zodpovědný za svou vlastní oblast: GUI, obchodní logiku, komponenty. Objevilo se oddělení analýzy, testování a architektury. Náklady na vývoj softwaru stouply stokrát a dokonce tisíckrát. Tento přístup k vývoji vyžaduje stabilní architekturu, která by vzájemně synchronizovala různé funkční oblasti produktu.
Vzory
Vzhledem k cíli snížení mzdových nákladů na vývoj komplexního softwaru předpokládáme, že je nutné používat hotová unifikovaná řešení. Šablonové akce totiž usnadňují komunikaci mezi vývojáři, umožňují odkazovat na známé návrhy a snižují počet chyb.
Podle Wikipedie je návrhový vzor opakovatelný architektonický návrh, který představuje řešení designového problému v nějakém často se vyskytujícím kontextu.

Začněme první hlavní věcí – Model-View-Controller. MVC je základní vzor, ​​který si našel cestu do mnoha technologií, dal vzniknout novým technologiím a každý den usnadňuje život vývojářům.

Vzor MVC se poprvé objevil v jazyce SmallTalk. Vývojáři museli přijít s architektonickým řešením, které by oddělilo grafické rozhraní od obchodní logiky a obchodní logiku od dat. Ve své klasické verzi se tedy MVC skládá ze tří částí, které mu dávají jméno. Pojďme se na ně podívat:

Model
Model je obvykle chápán jako část obsahující funkční obchodní logiku aplikace. Model musí být zcela nezávislý na zbytku produktu. Vrstva modelu nemusí vědět nic o prvcích návrhu ani o tom, jak bude vykreslen. Je dosaženo výsledku, který vám umožní změnit prezentaci dat, způsob jejich zobrazení, aniž byste se dotkli samotného modelu.

Model má následující vlastnosti:

  • Model je obchodní logikou aplikace;
  • Model má znalosti o sobě a neví o ovladačích a pohledech;
  • U některých projektů je model jednoduše datová vrstva (DAO, databáze, soubor XML);
  • Pro jiné projekty je modelem správce databáze, sada objektů nebo jednoduše aplikační logika;
Pohled
Mezi povinnosti Pohledu patří zobrazování dat přijatých z Modelu. Pohled však nemůže přímo ovlivnit model. Můžeme říci, že pohled má k datům přístup pouze pro čtení.

Reprezentace má následující vlastnosti:

  • Pohled implementuje zobrazení dat, která jsou získána z modelu jakýmkoli způsobem;
  • V některých případech může mít pohled kód, který implementuje nějakou obchodní logiku.
Příklady prezentace: HTML stránka, WPF formulář, Windows Form.
Rozdíly mezi MVP & MVVM & MVP
Nejběžnější typy vzorů MVC jsou:
  • Model-View-Controller
  • Model-View-Presenter
  • Model-View-View Model

Zvažme a porovnejme každý z nich.

Model-View-Presenter

Tento přístup umožňuje vytvořit reprezentační abstrakci. Chcete-li to provést, musíte vybrat rozhraní zobrazení se specifickou sadou vlastností a metod. Prezentující zase obdrží odkaz na implementaci rozhraní, přihlásí se k událostem prezentace a na požádání upraví model.

Známky moderátora:

  • Pohled interaguje přímo s předvádějícím voláním příslušných funkcí nebo událostí v instanci předvádějícího;
  • Prezentující komunikuje s Pohledem pomocí speciálního rozhraní implementovaného Pohledem;
  • Jedna instance presenteru je přidružena k jednomu displeji.

Implementace:
Každý pohled musí implementovat odpovídající rozhraní. Prezentační rozhraní definuje sadu funkcí a událostí potřebných k interakci s uživatelem (např. IView.ShowErrorMessage (řetězec msg)). Prezentující musí mít odkaz na implementaci odpovídajícího rozhraní, který je obvykle předán v konstruktoru.
Logika prezentace musí mít odkaz na instanci presenteru. Všechny události pohledu jsou předány ke zpracování prezentujícímu a téměř nikdy nejsou zpracovávány prezentační logikou (včetně vytváření dalších pohledů).

Příklad použití: Windows Forms.

Model-View-View Model


Tento přístup umožňuje přiřadit prvky pohledu k vlastnostem a událostem modelu pohledu. Lze namítnout, že každá vrstva tohoto vzoru neví o existenci další vrstvy.

Vlastnosti modelu View:

  • Obousměrná komunikace s prezentací;
  • Model pohledu je abstrakce pohledu. Obvykle to znamená, že vlastnosti pohledu jsou stejné jako vlastnosti pohledu/modelu
  • Model pohledu nemá odkaz na rozhraní pohledu (IView). Změna stavu modelu pohledu automaticky změní pohled a naopak, protože se používá mechanismus vazby dat (Vazby)
  • Jedna instance modelu pohledu je spojena s jedním pohledem.

Implementace:
Při použití tohoto vzoru pohled neimplementuje odpovídající rozhraní (IView).
Pohled musí mít odkaz na zdroj dat (DataContex), kterým je v tomto případě model pohledu. Prvky pohledu jsou svázány s odpovídajícími vlastnostmi a událostmi modelu pohledu.
Model pohledu zase implementuje speciální rozhraní, které se používá k automatické aktualizaci prvků pohledu. Příkladem takového rozhraní ve WPF by bylo INotifyPropertyChanged.

Příklad použití: WPF

Model-View-Controller

Hlavní myšlenkou tohoto vzoru je, že jak ovladač, tak pohled závisí na modelu, ale model nezávisí na těchto dvou komponentách.

Charakteristika regulátoru

  • Ovladač určuje, který pohled se má v daný okamžik zobrazit;
  • Události pohledu mohou ovlivnit pouze kontrolér Kontrolér může ovlivnit model a definovat jiný pohled.
  • Pro jeden ovladač je možné více zobrazení;

Implementace:
Ovladač zachytí událost zvenčí a v souladu s logikou v ní vloženou na tuto událost reaguje změnou Modelu zavoláním příslušné metody. Po změně model použije událost, která se změnila, a všechny k odběru přihlášené události View se poté, co ji přijmou, obrátí na model pro aktualizovaná data, načež se zobrazí.

Příklad použití: MVC ASP.NET

Resumé
Implementace vzorů MVVM a MVP na první pohled vypadá docela jednoduše a podobně. Pro MVVM se však vazba pohledu na View-model provádí automaticky, ale pro MVP je nutné naprogramovat
Zdá se, že MVC má větší kontrolu nad pohledem.
Obecná pravidla pro výběr vzoru
MVVM
  • Používá se v situaci, kdy je datová vazba možná bez nutnosti zavádět speciální rozhraní pro zobrazení (tj. není potřeba implementovat IView);
  • Běžným příkladem je technologie WPF.
MVP
  • Používá se v situaci, kdy není možná vazba dat (nelze použít vazbu);
  • Běžným příkladem by bylo použití Windows Forms.
MVC
  • Používá se v situaci, kdy není možná komunikace mezi pohledem a ostatními částmi aplikace (a nelze použít MVVM nebo MVP);
  • Běžným případem použití je ASP.NET MVC.
Závěr
Na závěr by autor tohoto článku rád podotkl, že striktně se držet pouze jednoho vzoru není vždy tou nejlepší volbou. Představte si například, že byste chtěli použít MVVM k vývoji aplikací pomocí Windows Forms prostřednictvím vlastnosti Bindings ovládacích prvků. Vaším cílem je oddělit prezentaci od obchodní logiky a logiky, která je spojuje. Aplikace by měla být snadno testovatelná a podporována a srozumitelná pro analytiky (ostatně na otázku „jak se měří výkon pevného disku“ existuje pouze jedna správná odpověď – v joulech (abstraktní příklad Model -> Zobrazení)) .

Děkuji moc za váš čas, užijte si čtení!




Nahoru