Fasáda (designový vzor)

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 4. července 2020; kontroly vyžadují 5 úprav .
Fasáda
fasáda
Typ strukturální
Popsáno v Návrhové vzory Ano

Vzor fasády (anglicky Facade ) je  strukturní návrhový vzor , ​​který vám umožňuje skrýt složitost systému snížením všech možných externích volání na jeden objekt a jejich delegováním na odpovídající objekty systému.

Popis

Problém

Jak zajistit jednotné rozhraní se sadou nesourodých implementací nebo rozhraní, například k subsystému, pokud je silné propojení s tímto subsystémem nežádoucí nebo se implementace subsystému může změnit?

Řešení

Definujte jeden bod interakce se subsystémem – objekt fasády, který poskytuje společné rozhraní se subsystémem, a svěřte mu odpovědnost za interakci s jeho komponentami. Fasáda je externí objekt, který poskytuje jediný vstupní bod pro služby subsystému. Implementace dalších komponent subsystému je soukromá a není viditelná pro externí komponenty. Objekt fasády poskytuje implementaci vzoru GRASP Resistant to changes (Protected Variations) z hlediska ochrany proti změnám v implementaci subsystému.

Vlastnosti aplikace

Šablona se používá k nastavení určitého druhu zásad pro jinou skupinu objektů. Pokud by politika měla být jasná a viditelná, měli byste použít služby šablony Facade. Pokud je nutné zajistit utajení a přesnost (transparentnost), je vhodnější volbou vzor proxy .

Příklady

C++

Zdrojový text v C++ #include <iostream> #include <řetězec> #include <paměť> #include <string_view> /** Abstraktní hudebník - není povinná součást vzoru, zavedena pro zjednodušení kódu */ třídní hudebník { const char * jméno ; veřejnost : Hudebník ( std :: string_viewname ) { _ toto -> jméno = jméno . data (); } virtuální ~ Hudebník () = výchozí ; chráněno : void output ( std :: string_view text ) { std :: cout << this -> jméno << "" << text << "." << std :: endl ; } }; /** Konkrétní hudebníci */ třída Zpěvák : public Musician { veřejnost : Zpěvák ( std :: string_view name ) : Hudebník ( name ) {} void singCouplet ( int coupletNumber ) { std :: string text = "zpíval sloku #" ; text += std :: to_string ( coupletNumber ); výstup ( text ); } void singChorus () { výstup ( "zpíval refrén" ); } }; třída kytarista : public Musician { veřejnost : Kytarista ( std :: string_view name ) : Hudebník ( name ) {} void playCoolOpening () { výstup ( "začíná skvělým úvodem" ); } void playCoolRiffs () { výstup ( "hraje skvělé riffy" ); } void playAnotherCoolRiffs () { výstup ( "hraje další skvělé riffy" ); } void playIncredablyCoolSolo () { výstup ( "vydá neuvěřitelně cool sólo" ); } void playFinalAccord () { výstup ( "ukončí skladbu silným akordem" ); } }; třída Baskytarista : public Musician { veřejnost : Basista ( std :: string_view name ) : Hudebník ( name ) {} void followTheDrums () { výstup ( "následuje kotouče" ); } void changeRhythm ( std :: string_viewtype ) { _ std :: string text = ( "přepnuto do rytmu" ); text += typ ; text += "a" ; výstup ( text ); } void stopPlaying () { výstup ( "přestane hrát" ); } }; třída Bubeník : public Musician { veřejnost : Bubeník ( std :: string_view name ) : Hudebník ( name ) {} void startPlaying () { výstup ( "začne hrát" ); } void stopPlaying () { výstup ( "přestane hrát" ); } }; /** Facade, v tomto případě slavná rocková kapela */ třída BlackSabbath { std :: unique_ptr < Vocalist > vocalist ; std :: unique_ptr < Kytarista > kytarista ; std :: unique_ptr < Basista > baskytarista ; std :: unique_ptr < Bubeník > bubeník ; veřejnost : BlackSabbath () { vocalist = std :: make_unique < Vocalist > ( "Ozzy Osbourne" ); kytarista = std :: make_unique < Kytarista > ( "Tony Iommi" ); basista = std :: make_unique < Basista > ( "Geezer Butler" ); bubeník = std :: make_unique < Bubeník > ( "Bill Ward" ); } void playCoolSong () { kytarista -> playCoolOpening (); bubeník -> začítHrát (); baskytarista -> followTheDrums (); kytarista -> playCoolRiffs (); zpěvák -> singCouplet ( 1 ); basista -> changeRhythm ( "refrén" ); kytarista -> hrátAnotherCoolRiffs (); zpěvák -> singChorus (); basista -> changeRhythm ( "verse" ); kytarista -> playCoolRiffs (); zpěvák -> singCouplet ( 2 ); basista -> changeRhythm ( "refrén" ); kytarista -> hrátAnotherCoolRiffs (); zpěvák -> singChorus (); basista -> changeRhythm ( "verse" ); kytarista -> hrátIncredablyCoolSolo (); kytarista -> playCoolRiffs (); zpěvák -> singCouplet ( 3 ); basista -> changeRhythm ( "refrén" ); kytarista -> hrátAnotherCoolRiffs (); zpěvák -> singChorus (); basista -> changeRhythm ( "verse" ); kytarista -> playCoolRiffs (); baskytarista -> stopPlaying (); bubeník -> stopPlaying (); kytarista -> playFinalAccord (); } }; int main () { std :: cout << "VYSTUP:" << std :: endl ; kapela BlackSabbath ; kapela . playCoolSong (); návrat 0 ; } /** * VÝSTUP: * Tony Iommi začíná skvělým intrem. * Bill Ward začíná hrát. * Geezer Butler následuje bubny. * Tony Iommi hraje skvělé riffy. * Ozzy Osbourne zpíval verš #1. * Geezer Butler přešel na sborový rytmus. * Tony Iommi hraje další skvělé riffy. * Ozzy Osbourne zpíval refrén. * Geezer Butler přešel do rytmu verše. * Tony Iommi hraje skvělé riffy. * Ozzy Osbourne zpíval verš #2. * Geezer Butler přešel na sborový rytmus. * Tony Iommi hraje další skvělé riffy. * Ozzy Osbourne zpíval refrén. * Geezer Butler přešel do rytmu verše. * Tony Iommi přináší neuvěřitelně cool sólo. * Tony Iommi hraje skvělé riffy. * Ozzy Osbourne zpíval sloku č. 3. * Geezer Butler přešel na sborový rytmus. * Tony Iommi hraje další skvělé riffy. * Ozzy Osbourne zpíval refrén. * Geezer Butler přešel do rytmu verše. * Tony Iommi hraje skvělé riffy. * Geezer Butler přestane hrát. * Bill Ward přestane hrát. * Tony Iommi končí píseň silným akordem. */

JavaScript

Zdrojový kód JavaScriptu /* Složité části */ function SubSystem1 () { this . metoda1 = funkce () { konzole . log ( "SubSystem1.metoda1 volána" ); }; } function SubSystem2 () { this . metoda2 = funkce () { konzole . log ( "SubSystem2.metoda2 volána" ); }; toto . methodB = function () { console . log ( "SubSystem2.metodaB volána" ); }; } /* Fasáda */ funkce Fasáda () { var s1 = new SubSystem1 (), s2 = new SubSystem2 (); toto . m1 = funkce () { konzole . log ( "Fasáda.m1 volána" ); s1 . metoda1 (); s2 . metoda2 (); }; toto . m2 = funkce () { konzole . log ( "Fasáda.m2 volána" ); s2 . metoda B (); }; } /* Klient */ test funkce () { var fasáda = nová fasáda (); fasáda . ml (); fasáda . m2 (); } test (); /* Výstup: "Facade.m1 volána" " SubSystem1.method1 volá" "SubSystem2.method2 je volána " "Facade.m2 volá" "SubSystem2.methodB volá " */

CoffeeScript

Zdrojový text v jazyce CoffeeScript # Třída načítání obrázků ImageLoader loadImage = (src) -> # ... konstruktor: (hash = {}) -> @images = {} @images [ název ] = loadImage ( src ) pro jméno , zdroj hash # Třída Audio loader SoundLoader loadSound = (src) -> # ... konstruktor: (hash = {}) -> @sounds = {} @sounds [ name ] = loadSound ( src ) pro jméno , zdroj hash # Facade class Loader konstruktor : ({images, sounds}) -> @images = new ImageLoader ( images ). obrázky @sounds = nový SoundLoader ( zvuky ). zvuky zvuk : (jméno) -> @zvuky [ jméno ] obrázek : (jméno) -> @obrázky [ jméno ]

PHP

Zdrojový kód PHP /** * Implementace jednotlivých částí počítače. * Každá metoda třídy má nějaký druh implementace, v tomto příkladu je vynechána. */ /** * Třída CPU, zodpovědná za běh CPU */ class CPU { zmrazení veřejné funkce () {} skok veřejné funkce ( $ pozice ) {} spuštění veřejné funkce () {} } /** * Paměť třídy, zodpovědná za činnost paměti */ class Paměť { const BOOT_ADDRESS = 0x0005 ; zatížení veřejné funkce ( $position , $data ) {} } /** * Pevný disk třídy, zodpovědný za provoz pevného disku */ class Pevný disk { const BOOT_SECTOR = 0x001 ; const VELIKOST_SECTORU = 64 ; veřejná funkce čtení ( $lba , $velikost ) {} } /** * Příklad vzoru "Fasáda" * Počítač se používá jako jednotný objekt. * Za tímto objektem budou skryty všechny detaily práce jeho vnitřních částí. */ class Počítač { protected $cpu ; chráněná $paměť ; chráněný $pevný disk ; /** * Konstruktor počítače. * Inicializace částí */ public function __construct () { $this -> cpu = new CPU (); $this -> memory = new Memory (); $this -> pevný disk = nový pevný disk (); } /** * Zjednodušená manipulace s chováním "spuštění počítače" */ public function startComputer () { $cpu = $this -> cpu ; $paměť = $toto -> paměť ; $hardDrive = $this -> pevný disk ; $cpu -> zmrazení (); $memory -> load ( $memory :: BOOT_ADDRESS , $hardDrive -> read ( $hardDrive :: BOOT_SECTOR , $hardDrive :: SECTOR_SIZE ) ); $cpu -> skok ( $paměť :: BOOT_ADDRESS ); $cpu -> provést (); } } /** * Uživatelé počítačů mají k dispozici Fasádu (počítač) *, která skrývá veškerou složitost práce s jednotlivými komponentami. */ $počítač = nový počítač (); $computer -> startComputer ();

Python

Zdrojový kód v Pythonu # Komplexní části systémové třídy CPU ( object ): def __init__ ( self ): # ... pass def freeze ( self ): # ... projít def skok ( self , adresa ): # ... pass def vykonat ( self ): # ... projít class Paměť ( objekt ): def __init__ ( self ): # ... pass def load ( self , position , data ): # ... pass třída Pevný disk ( objekt ): def __init__ ( self ): # ... pass def read ( self , lba , size ): # ... pass # Facade class Počítač ( objekt ): def __init__ ( self ): self . _cpu = cpu () self . _memory = Memory () self . _harddrive = pevný disk () def startComputer ( self ): self . _cpu . zmrazit () sebe . _paměť . načíst ( BOOT_ADDRESS , self . _hardDrive . read ( BOOT_SECTOR , SECTOR_SIZE )) self . _cpu . skok ( BOOT_ADDRESS ) self . _cpu . provést () # Strana klienta if __name__ == "__main__" : fasáda = Počítačová () fasáda . startComputer ()

C#

Zdrojový text v C# pomocí System ; jmenný prostor knihovna { /// <summary> /// Subsystem class /// </summary> /// <remarks> /// <li> /// <lu>implementuje funkčnost subsystému;</lu> /// <lu>provádí práci zadanou objektem <viz cref="Fasáda"/>;</lu> /// <lu>neví" nic o existenci fasády, tedy neukládá odkazy na něj;</lu> / // </li> /// </remarks> vnitřní třída SubsystémA { vnitřní řetězec A1 () { return "Subsystém A, metoda A1\n" ; } vnitřní řetězec A2 () { return "Podsystém A, metoda A2\n" ; } } interní třída SubsystémB { vnitřní řetězec B1 () { return "Subsystém B, metoda B1\n" ; } } interní třída SubsystemC { vnitřní řetězec C1 () { return "Subsystém C, metoda C1\n" ; } } } /// <summary> /// Fasáda - fasáda /// </summary> /// <remarks> /// <li> /// <lu>"ví", se kterými třídami subsystému má žádost adresovat;< /lu > /// <lu>delegovat požadavky klientů na příslušné objekty v rámci subsystému;</lu> /// </li> /// </remarks> public class Facade { Library . SubsystémA a = nová knihovna . SubsystémA (); knihovna . SubsystemB b = new Library . SubsystémB (); knihovna . SubsystemC c = new Library . Subsystém C (); public void Operace1 () { Konzole . WriteLine ( "Operace 1\n" + a . A1 () + a . A2 () + b . B1 ()); } public void Operation2 () { Console . WriteLine ( "Operace 2\n" + b . B1 () + c . C1 ()); } } class Program { static void Main ( string [] args ) { Fasáda fasáda = nová Fasáda (); fasáda . Operace1 (); fasáda . Operace2 (); // Počkejte na uživatelskou konzoli . číst (); } }

Ruby

Zdrojový text v rubínovém jazyce modul Knihovna # <summary> # Třída subsystému # </summary> # <remarks> # <li> # <lu>implementuje funkcionalitu subsystému;</lu> # <lu>provádí úlohu přidělenou <see cref="Facade"/> ;</lu> # <lu>neví" nic o existenci fasády, to znamená, že na ni neukládá odkazy;</lu> # </li> # </remarks> class SubsystemA def a1 ; "Podsystém A, metoda a1 \n " ; enddef a2 ; _ "Podsystém A, metoda a2 \n " ; konec konec class SubsystemB def b1 ; "Podsystém B, metoda b1 \n " ; konec konec class SubsystemC def c1 ; "Podsystém C, metoda c1 \n " ; konec konec konec # <summary> # Facade # </summary> # <remarks> # <li> # <lu>"ví", kterým podsystémovým třídám adresovat požadavky;</lu> # <lu>deleguje požadavky klientům na příslušné objekty v rámci subsystém ;</lu> # </li> # </remarks> třída Fasáda def initialize @a = Library :: SubsystemA . nový ; @b = Library :: SubsystemB . nový ; @c = Library :: SubsystemC . nový ; konec def operation1 vloží "Operace 1 \n " + @a . a1 + @a . a2 + @b . konec b1 def operation2 vloží "Operation 2 \n " + @b . b1 () + @c . c1 () konec konec fasáda = fasáda . nová fasáda . provoz1 fasáda . provoz2 # Počkejte, až uživatel dostane

VB.NET

Zdrojový text v jazyce VB.NET Knihovna jmenného prostoru 'Třída subsystému '. implementuje funkcionalitu subsystému ' . provádí práci zadanou objektem Fasáda '. „neví“ nic o existenci fasády, to znamená, že na ni neukládá odkazy Friend Class SubsystemA Friend Function A1 () As String Return „Subsystem A, Method A1“ & vbCrLf End Function Friend Function A2 () As String Return "Subsystem A, Method A2" & vbCrLf End Function End Class Třída přítele SubsystémB Funkce přítele B1 () Jako řetězec Návrat "Subsystém B, metoda B1" & vbCrLf Koncová funkce Koncová třída Třída přítele SubsystémC Funkce přítele C1 () jako řetězec Návrat "Subsystém C, metoda C1" & vbCrLf Koncová funkce End Class konec jmenného prostoru 'Fasáda '. "ví", které třídy subsystému mají řešit požadavek ' . deleguje požadavky klientů na příslušné objekty v rámci podsystému Public NotInheritable Class Facade Private Sub New () End Sub Sdílel jako novou knihovnu . _ SubsystemA () Shared b As New Library . SubsystemB () Shared c As New Library . Subsystém C () Veřejná sdílená dílčí operace1 () Konzola . WriteLine ( "Operace 1" & vbCrLf & a . A1 () & a . A2 () & b . B1 ()) End Sub Veřejná sdílená dílčí operace2 () Konzola . WriteLine ( "Operace 2" & vbCrLf & b . B1 () & c . C1 ()) End Sub End Class třídní program Sdílená dílčí hlavní () fasáda . Operace1 () Fasáda . Operation2 () 'Čekání na akci uživatele Konzole . Číst () End Sub End Class

Delphi

Zdrojový text v Delphi program FacadePattern ; {$APPTYPE KONZOLE} používá SysUtils ; typ TComputer = class public procedure PlugIn ; postup PowerMonitor ; postup Síla ; konec ; postup TComputer . Plug In ; begin WriteLn ( 'Zahrnuto v síti' ) ; konec ; postup TComputer . PowerMonitor ; begin WriteLn ( 'Zapnout monitor' ) ; konec ; postup TComputer . moc ; begin WriteLn ( 'Otočte systémovou jednotku' ) ; konec ; typ TNotebook = class procedure Power ; konec ; postup TNotebook . moc ; begin WriteLn ( 'Stiskněte vypínač' ) ; konec ; typ TKettle = class procedure PlugIn ; postup Síla ; konec ; postup TKettle . moc ; begin WriteLn ( 'Stiskněte vypínač' ) ; konec ; postup TKettle . Plug In ; begin WriteLn ( 'Zahrnuto v síti' ) ; konec ; typ TFacade = class public procedure PowerOn ( aDevice : TObject ) ; konec ; postup TFasáda . PowerOn ( aDevice : TObject ) ; begin , pokud je aDevice TComputer , pak s TComputer ( aDevice ) do begin PlugIn ; PowerMonitor ; moc ; konec ; pokud je aDevice TNotebook, pak s TNotebook ( aDevice ) proveďte Power ; pokud je aDevice TKettle , pak s TKettle ( aDevice ) spusťte PlugIn ; moc ; konec ; WriteLn end ; začněte s TFacade . Create do try PowerOn ( TComputer . Create ) ; PowerOn ( TNotebook.Create ) ; _ _ PowerOn ( TKettle.Create ) ; _ _ konečně zdarma ; konec ; Readln ; konec .

Java

Zdroj Java /* Složité části */ class CPU { public void freeze () { System . ven . println ( "zmrazit" ); } public void jump ( long position ) { System . ven . println ( "pozice skoku = " + pozice ); } public void vykonat () { System . ven . println ( "provést" ); } } class Paměť { public void load ( long position , byte [ ] data ) { System . ven . println ( "pozice načtení = " + pozice + ", data = " + data ); } } class HardDrive { public byte [] read ( long lba , int size ) { System . ven . println ( "čti lba = " + lba + ", velikost = " + velikost ); vrátit nový byte [ velikost ] ; } } /* Fasáda */ class Počítač { private final static long BOOT_ADDRESS = 1L ; private final static long BOOT_SECTOR = 2L ; private final static int VELIKOST_SEKTORU = 3 ; soukromý procesor CPU ; soukromá paměť ; _ soukromý pevný disk pevný disk ; public Computer () { this . cpu = nový cpu (); toto . paměť = nová paměť (); toto . pevný disk = nový pevný disk (); } public void startComputer () { cpu . zmrazit (); paměť . načíst ( BOOT_ADDRESS , pevný disk . čtení ( BOOT_SECTOR , SECTOR_SIZE )); cpu . skok ( BOOT_ADDRESS ); cpu . provést (); } } /* Klient */ class Aplikace { public static void main ( String [] args ) { Počítač počítač = nový Počítač (); počítač . startComputer (); } }

haxe

Zdrojový text v jazyce Haxe /** * Implementace jednotlivých částí počítače. * Každá metoda třídy má nějaký druh implementace, v tomto příkladu je vynechána. */ /** * Třída CPU, zodpovědná za provoz procesoru */ class CPU { public function new () { } public function freeze (): Void { //... } public function jump ( position : Int ): Void { //... } public function execute (): Void { //... } } /** * Paměť třídy, zodpovědná za operace paměti */ class Paměť { public static inline var BOOT_ADDRESS : Int = 0x0005 ; public function new () { } zatížení veřejné funkce ( pozice : Int , data : haxe . io . Bajty ): Void { //... } } /** * Pevný disk třídy, zodpovědný za provoz pevného disku */ class Pevný disk { public static inline var BOOT_SECTOR : Int = 0x001 ; public static inline var SECTOR_SIZE : Int = 64 ; public function new () { } public function read ( lba : Int , size : Int ): haxe . io . Bajty { //... return null ; } } /** * Příklad vzoru "Fasáda" * Počítač se používá jako jednotný objekt. * Za tímto objektem budou skryty všechny detaily práce jeho vnitřních částí. */ class Počítač { private var cpu : CPU ; private var memory : Memory ; soukromý var pevný disk : Pevný disk ; /** * Konstruktor počítače. * Inicializovat části */ public function new () { this . cpu = nový cpu (); toto . paměť = nová paměť (); toto . pevný disk = nový pevný disk (); } /** * Zjednodušené zpracování chování "spuštění počítače" */ public function startComputer (): Void { cpu . zmrazit (); paměť . načíst ( Paměť . BOOT_ADDRESS , pevný disk . čtení ( Pevný disk . BOOT_SECTOR , Pevný disk . SECTOR_SIZE ) ); cpu . skok ( Memory.BOOT_ADDRESS ) ; _ cpu . provést (); } } /** * Uživatelé počítačů mají k dispozici Fasádu (počítač) *, která skrývá veškerou složitost práce s jednotlivými komponentami. */ class Aplikace { public static function main (): Void { var computer : Computer = new Computer (); počítač . startComputer (); } }

Swift

Rychlý zdrojový kód // Logic class CPU { public func freeze () -> String { return "Zamrzání procesoru." } public func skok ( pozice : String ) -> String { return " Skok na: \ ( pozice ) " } public func execute () -> String { return "Probíhá." } } třída paměť { public func load ( position : String , data : String ) -> String { return "Načítání z \( pozice ) dat: \( data ) " } } pevný disk třídy { public func read ( lba : String , size : String ) -> String { return "Některá data ze sektoru \( lba ) o velikosti \( size ) " } } //Fasáda class ComputerFacade { private let cpu = CPU () private let memory = Memory () private let harddisk = HardDrive () public func start () { cpu . zmrazit () nechat ssd = pevný disk . čtení ( lba : "100" , velikost : "1024" ) paměť . zatížení ( pozice : "0x00" , data : ssd ) cpu . skok ( pozice : "0x00" ) cpu . provést () } } // Klient nechť pc = ComputerFacade () pc . začít ()

Literatura

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Techniky objektově orientovaného navrhování. Design Patterns = Design Patterns: Prvky opakovaně použitelného objektově orientovaného softwaru. - Petrohrad. : " Petr ", 2007. - S. 366. - ISBN 978-5-469-01136-1 . (také ISBN 5-272-00355-1 )

Zdroje a odkazy