Fațadă (model de design)

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită pe 4 iulie 2020; verificările necesită 5 modificări .
Faţadă
faţadă
Tip de structural
Descris în Design Patterns da

Modelul de fațadă ( ing.  Fațadă ) este un model de proiectare structurală care vă permite să ascundeți complexitatea sistemului prin reducerea tuturor apelurilor externe posibile la un singur obiect , delegându-le obiectelor corespunzătoare ale sistemului.

Descriere

Problemă

Cum se oferă o interfață unificată cu un set de implementări sau interfețe disparate, de exemplu, unui subsistem, dacă cuplarea puternică la acel subsistem nu este de dorit sau implementarea subsistemului s-ar putea schimba?

Soluție

Definiți un punct de interacțiune cu subsistemul - un obiect de fațadă care oferă o interfață comună cu subsistemul și încredințați-i responsabilitatea de a interacționa cu componentele sale. O fațadă este un obiect extern care oferă un singur punct de intrare pentru serviciile subsistemului. Implementarea altor componente ale subsistemului este privată și nu este vizibilă pentru componentele externe. Obiectul de fațadă oferă implementarea GRASP a modelului Variații protejate în ceea ce privește protecția împotriva modificărilor în implementarea subsistemului.

Caracteristicile aplicației

Un șablon este folosit pentru a seta un fel de politică pentru un alt grup de obiecte. Dacă politica ar trebui să fie strălucitoare și vizibilă, ar trebui să utilizați serviciile șablonului Fațadă. Dacă este necesar să oferiți secret și acuratețe (transparență), modelul Proxy este o alegere mai potrivită .

Exemple

C++

Text sursă în C++ #include <iostream> #include <șir> #include <memorie> #include <string_view> /** Muzician abstract - nu este o parte obligatorie a modelului, introdus pentru a simplifica codul */ clasa muzician { const char * nume ; public : Muzician ( std :: string_viewname ) { _ asta -> nume = nume . date (); } virtual ~ Muzician () = implicit ; protejat : void output ( std :: string_view text ) { std :: cout << this -> name << "" << text << "." << std :: endl ; } }; /** Muzicieni specifici */ clasa vocalist : muzician public { public : Vocalist ( std :: string_view name ) : muzician ( nume ) {} void singCouplet ( int coupletNumber ) { std :: string text = "sang vers #" ; text += std :: to_string ( coupletNumber ); ieșire ( text ); } void sing Refren () { ieșire ( „a cântat refrenul” ); } }; clasa Chitarist : muzician public { public : Chitarist ( std :: string_view name ) : Muzician ( nume ) {} void playCoolOpening () { ieșire ( „începe cu o introducere cool” ); } void playCoolRiffs () { ieșire ( „reda riff-uri cool” ); } void playAnotherCoolRiffs () { ieșire ( „reda alte riff-uri cool” ); } void playIncrediblyCoolSolo () { ieșire ( " scoate un solo incredibil de cool " ); } void playFinalAccord () { ieșire ( „termină melodia cu un acord puternic” ); } }; clasa Basist : muzician public { public : Basist ( std :: string_view name ) : muzician ( nume ) {} void followTheDrums () { ieșire ( „urmează rolele” ); } void changeRhythm ( std :: string_viewtype ) { _ std :: string text = ( "s-a comutat la ritm" ); text += tip ; text += "a" ; ieșire ( text ); } void stopPlaying () { ieșire ( „se oprește redarea” ); } }; clasă Toboșar : muzician public { public : Toboșar ( std :: string_view name ) : Muzician ( nume ) {} void startPlaying () { ieșire ( „începe redarea” ); } void stopPlaying () { ieșire ( „se oprește redarea” ); } }; /** Fațadă, în acest caz o trupă rock faimoasă */ clasa BlackSabbath { std :: unique_ptr < Vocalist > vocalist ; std :: unique_ptr < Chitarist > chitarist ; std :: unique_ptr < Basist > basist ; std :: unique_ptr < Drummer > baterist ; public : BlackSabbath () { vocalist = std :: make_unique < Vocalist > ( „Ozzy Osbourne” ); chitarist = std :: make_unique < Guitarist > ( „Tony Iommi” ); basist = std :: make_unique < Basist > ( „Geezer Butler” ); drummer = std :: make_unique < Drummer > ( „Bill Ward” ); } void playCoolSong () { chitarist -> playCoolOpening (); baterist -> startPlaying (); basist -> followTheDrums (); chitarist -> playCoolRiffs (); vocalist -> singCouplet ( 1 ); basist -> changeRhythm ( " refren " ); chitarist -> playAnotherCoolRiffs (); vocalist -> singChorus (); basist -> changeRhythm ( „vers” ); chitarist -> playCoolRiffs (); vocalist -> singCouplet ( 2 ); basist -> changeRhythm ( " refren " ); chitarist -> playAnotherCoolRiffs (); vocalist -> singChorus (); basist -> changeRhythm ( „vers” ); chitarist -> playIncrediblyCoolSolo (); chitarist -> playCoolRiffs (); vocalist -> singCouplet ( 3 ); basist -> changeRhythm ( " refren " ); chitarist -> playAnotherCoolRiffs (); vocalist -> singChorus (); basist -> changeRhythm ( „vers” ); chitarist -> playCoolRiffs (); basist -> stopPlaying (); baterist -> stopPlaying (); chitarist -> playFinalAccord (); } }; int main () { std :: cout << "OUTPUT:" << std :: endl ; trupa BlackSabbath ; banda . playCoolSong (); returnează 0 ; } /** * IEȘIRE: * Tony Iommi începe cu o intro cool. * Bill Ward începe să joace. * Geezer Butler urmează tobe. * Tony Iommi joacă riff-uri grozave. * Ozzy Osbourne a cântat versetul #1. * Geezer Butler a trecut la ritmul corului. * Tony Iommi joacă alte riff-uri interesante. * Ozzy Osbourne a cântat refrenul. * Geezer Butler a trecut la ritmul versului. * Tony Iommi joacă riff-uri grozave. * Ozzy Osbourne a cântat versetul #2. * Geezer Butler a trecut la ritmul corului. * Tony Iommi joacă alte riff-uri interesante. * Ozzy Osbourne a cântat refrenul. * Geezer Butler a trecut la ritmul versului. * Tony Iommi oferă un solo incredibil de cool. * Tony Iommi joacă riff-uri grozave. * Ozzy Osbourne a cântat versetul #3. * Geezer Butler a trecut la ritmul corului. * Tony Iommi joacă alte riff-uri interesante. * Ozzy Osbourne a cântat refrenul. * Geezer Butler a trecut la ritmul versului. * Tony Iommi joacă riff-uri grozave. * Geezer Butler nu mai joacă. * Bill Ward nu mai joacă. * Tony Iommi încheie melodia cu un acord puternic. */

JavaScript

Cod sursă JavaScript /* Părți complexe */ function SubSystem1 () { this . method1 = function () { consola . log ( "SubSystem1.method1 apelat" ); }; } function SubSystem2 () { this . method2 = function () { consola . log ( "SubSystem2.method2 apelat" ); }; aceasta . methodB = function () { console . log ( "SubSystem2.methodB numit" ); }; } /* Fațadă */ function Fațadă () { var s1 = nou SubSystem1 (), s2 = nou SubSystem2 (); aceasta . m1 = function () { consola . jurnal ( "Fațada.m1 numit" ); s1 . metoda1 (); s2 . metoda2 (); }; aceasta . m2 = function () { consola . jurnal ( "Fațada.m2 numit" ); s2 . metodaB (); }; } /* Client */ function test () { var fatada = nou Fatada (); fatada . m1 (); fatada . m2 (); } test (); /* Ieșire: "Facade.m1 numit" "SubSystem1.method1 numit" "SubSystem2.method2 numit" "Facade.m2 numit" "SubSystem2.methodB numit" */

CoffeeScript

Text sursă în limbajul CoffeeScript # Clasa încărcător de imagini ImageLoader loadImage = (src) -> # ... constructor: (hash = {}) -> @images = {} @images [ name ] = loadImage ( src ) for name , src of hash # Clasa de încărcare audio SoundLoader loadSound = (src) -> # ... constructor: (hash = {}) -> @sounds = {} @sounds [ nume ] = loadSound ( src ) pentru nume , src de hash # Clasa de fațadă Loader constructor : ({imagini, sunete}) -> @images = new ImageLoader ( imagini ). imagini @sounds = nou SoundLoader ( sunete ). sunete sunet: (nume) -> @sunete [ nume ] imagine : (nume) -> @imagini [ nume ]

PHP

Cod sursă PHP /** * Implementări ale părților individuale ale computerului. * Fiecare metodă de clasă are un fel de implementare, în acest exemplu este omisă. */ /** * Class CPU, responsabil pentru rularea CPU */ class CPU { public function freeze () {} public function jump ( $position ) {} public function execute () {} } /** * Memorie de clasă, responsabilă pentru operarea memoriei */ Memorie de clasă { const BOOT_ADDRESS = 0x0005 ; încărcare funcție publică ( $poziție , $date ) {} } /** * Class HardDrive, responsabil pentru funcționarea hard diskului */ class HardDrive { const BOOT_SECTOR = 0x001 ; const SECTOR_SIZE = 64 ; citire funcție publică ( $lba , $size ) {} } /** * Un exemplu de model „Fațadă” * Computerul este folosit ca obiect unificat. * În spatele acestui obiect vor fi ascunse toate detaliile lucrării părților sale interne. */ class Computer { protected $cpu ; protejat $memorie ; protejat $hardDrive ; /** * Constructor de computer. * Initialize parts */ public function __construct () { $this -> cpu = new CPU (); $this -> memory = new Memory (); $this -> hardDrive = hard disk nou (); } /** * Gestionarea simplificată a comportamentului „pornire computer” */ public function startComputer () { $cpu = $this -> cpu ; $memorie = $aceasta -> memorie ; $hardDrive = $this -> hardDrive ; $cpu -> freeze (); $memorie -> încărcare ( $memorie :: BOOT_ADDRESS , $hardDrive -> citire ( $hardDrive :: BOOT_SECTOR , $hardDrive :: SECTOR_SIZE ) ); $cpu -> jump ( $memorie :: BOOT_ADDRESS ); $cpu -> execute (); } } /** * Utilizatorii de computere au la dispoziție o fațadă (computer) * care ascunde toată complexitatea lucrului cu componente individuale. */ $computer = computer nou (); $computer -> startComputer ();

Python

Cod sursă în Python # Părți complexe ale clasei de sistem CPU ( obiect ): def __init__ ( self ): # ... trece def freeze ( self ): # ... trece def jump ( self , address ): # ... trece def execute ( self ): # ... trece clasa Memorie ( obiect ): def __init__ ( self ): # ... trece def load ( self , position , data ): # ... trece clasa HardDrive ( obiect ): def __init__ ( self ): # ... trece def read ( self , lba , size ): # ... trece # Clasa fațadă Computer ( obiect ): def __init__ ( self ): self . _cpu = cpu () self . _memory = Memory () self . _harddrive = hard disk () def startComputer ( self ): sine . _cpu . freeze () self . _memorie . încărcați ( BOOT_ADDRESS , self . _hardDrive . read ( BOOT_SECTOR , SECTOR_SIZE )) self . _cpu . sari ( BOOT_ADDRESS ) auto . _cpu . executa () # Client side if __name__ == "__main__" : fațadă = computer () fațadă . startComputer ()

C#

Text sursă în C# folosind System ; Bibliotecă namespace { /// <summary> /// Clasa subsistemului /// </summary> /// <remarks> /// <li> /// <lu>implementează funcționalitatea subsistemului;</lu> /// <lu>realizează lucrarea atribuită de obiectul <see cref="Facade"/>;</lu> /// <lu>nu „știe” nimic despre existența fațadei, adică nu stochează referințe la acesta;</lu> / // </li> /// </remarks> internal class SubsystemA { internal string A1 () { return "Subsystem A, Method A1\n" ; } șir intern A2 () { return „Subsistem A, Metoda A2\n” ; } } internal class SubsystemB { internal string B1 () { return "Subsistem B, Metoda B1\n" ; } } internal class SubsystemC { internal string C1 () { return "Subsystem C, Method C1\n" ; } } } /// <summary> /// Fațadă - fațadă /// </summary> /// <remarks> /// <li> /// <lu>„știe” cu ce clase de subsistem să adreseze cererea;< /lu > /// <lu>delegați cererile client la obiectele corespunzătoare din subsistem;</lu> /// </li> /// </remarks> public class Fațadă { Library . SubsistemA a = bibliotecă nouă . SubsistemulA (); biblioteca . SubsistemB b = Bibliotecă nouă . Subsistemul B (); biblioteca . SubsistemC c = bibliotecă nouă . SubsistemulC (); public void Operation1 () { Consolă . WriteLine ( "Operația 1\n" + a . A1 () + a . A2 () + b . B1 ()); } public void Operation2 () { Consola . WriteLine ( "Operațiunea 2\n" + b . B1 () + c . C1 ()); } } class Program { static void Main ( string [] args ) { Fațada fațadă = nou Fațadă (); fatada . Operațiunea1 (); fatada . Operațiunea2 (); // Așteptați Consola utilizatorului . citește (); } }

Ruby

Text sursă în limba rubin modul Biblioteca # <summary> # Clasa subsistemului # </summary> # <remarks> # <li> # <lu>implementează funcționalitatea subsistemului;</lu> # <lu>realizează treaba atribuită de <see cref="Facade"/> ;</lu> # <lu>nu „știe” nimic despre existența fațadei, adică nu stochează referințe la aceasta;</lu> # </li> # </remarks> class SubsystemA def a1 ; „Subsistemul A, Metoda a1 \n ; enddef a2 ; _ „Subsistemul A, Metoda a2 \n ; sfârşitul sfârşitului clasa SubsistemB def b1 ; „Subsistemul B, Metoda b1 \n ; sfârşitul sfârşitului clasa SubsistemC def c1 ; „Subsistemul C, Metoda c1 \n ; sfârșit sfârșit sfârșit # <summary> # Fațada # </summary> # <remarks> # <li> # <lu>„știe” căror clase de subsistem să adreseze cererile;</lu> # <lu>delegă cererile clienților la obiectele corespunzătoare din subsistemul ;</lu> # </li> # </remarks> clasa Fațadă def initialize @a = Library :: SubsystemA . nou ; @b = Bibliotecă :: SubsistemB . nou ; @c = Bibliotecă :: SubsystemC . nou ; Sfârşit def operation1 pune „Operațiunea 1 \n + @a . a1 + @a . a2 + @b . b1 sfârşitul def operation2 pune „Operațiunea 2 \n + @b . b1 () + @c . c1 () sfârşit capăt façade = façade . fatada noua . operațiune1 fațadă . operare2 # Așteptați ca utilizatorul să primească

VB.NET

Text sursă în limba VB.NET Biblioteca de spații de nume „Clasa de subsistem ” . implementează funcționalitatea subsistemului ' . execută lucrarea atribuită de obiectul Fațadă ' . nu „știe” nimic despre existența fațadei, adică nu stochează referințe la aceasta Friend Class SubsystemA Friend Function A1 () As String Return „Subsystem A, Method A1” & vbCrLf End Function Funcția Friend A2 () Ca șir Returnează „Subsistem A, Metoda A2” și vbCrLf End Function End Class Clasa prieten SubsistemB Funcție prieten B1 () Ca șir Returnare „Subsistem B, Metoda B1” și vbCrLf Clasa finală a funcției de final Clasa prieten SubsistemC Funcție prieten C1 () Ca șir Returnează „Subsistem C, Metoda C1” și vbCrLf Clasa finală a funcției de sfârșit sfârșitul spațiului de nume 'Fațadă '. „știe” ce clase de subsistem să adreseze cererea ’ . delegă solicitările clientului către obiectele corespunzătoare din subsistemul Public NotInheritable Class Facade Private Sub New () End Sub Partajat o bibliotecă ca nouă . SubsistemA () Partajat b Ca bibliotecă nouă . SubsistemB () Partajat c ca bibliotecă nouă . SubsistemulC () Suboperațiune publică partajată1 ( ) Consola . WriteLine ( „Operațiunea 1” și vbCrLf și a . A1 () și a . A2 () și b . B1 ()) End Sub Suboperațiune publică partajată2 ( ) Consola . WriteLine ( "Operațiunea 2" & vbCrLf & b . B1 () & c . C1 ()) End Sub End Class programul clasei Sub principal comun () Fațadă . Operațiunea1 () Fațadă . Operațiunea 2 () „Se așteaptă acțiunea utilizatorului Consola . Citiți () End Sub End Class

Delphi

Text sursă în Delphi program FacadePattern ; {$APPTYPE CONSOLE} folosește SysUtils ; tip TComputer = clasă procedură publică PlugIn ; procedura PowerMonitor ; procedura Putere ; sfârşitul ; procedura TComputer . Conectare ; începe WriteLn ( 'Inclus în rețea' ) ; sfârşitul ; procedura TComputer . PowerMonitor ; începe WriteLn ( 'Porniți monitorul' ) ; sfârşitul ; procedura TComputer . putere ; începe WriteLn ( „Întoarce unitatea de sistem” ) ; sfârşitul ; tip TNotebook = procedură de clasă Putere ; sfârşitul ; procedura TNotebook . putere ; începe WriteLn ( „Apăsați butonul de pornire” ) ; sfârşitul ; tip TKettle = procedura de clasă PlugIn ; procedura Putere ; sfârşitul ; procedura TKettle . putere ; începe WriteLn ( „Apăsați butonul de pornire” ) ; sfârşitul ; procedura TKettle . Conectare ; începe WriteLn ( 'Inclus în rețea' ) ; sfârşitul ; tip TFacade = clasă procedură publică PowerOn ( aDevice : TObject ) ; sfârşitul ; procedura TFacade . Pornire ( un dispozitiv : TObject ) ; începe dacă aDevice este TComputer , apoi cu TComputer ( aDevice ) începe PlugIn ; PowerMonitor ; putere ; sfârşitul ; dacă aDevice este TNotebook , atunci cu TNotebook ( aDevice ) faceți Power ; dacă un dispozitiv este TKettle , atunci cu TKettle ( aDevice ) începe PlugIn ; putere ; sfârşitul ; WriteLn end ; începe cu TFacade . Creați , încercați PowerOn ( TComputer . Creați ) ; Pornire ( TNotebook.Create ) ; _ _ Pornire ( TKettle.Create ) ; _ _ in sfarsit Gratuit ; sfârşitul ; Readln ; sfârşitul .

Java

Sursa Java /* Piese complexe */ class CPU { public void freeze () { System . afară . println ( "înghețare" ); } public void jump ( poziție lungă ) { System . afară . println ( "poziție de salt = " + poziție ); } public void execute () { System . afară . println ( "executa" ); } } class Memory { public void load ( poziție lungă , octet [] date ) { System . afară . println ( "poziție de încărcare = " + poziție + ", date = " + date ); } } class HardDrive { public byte [] read ( long lba , int size ) { System . afară . println ( "citește lba = " + lba + ", dimensiune = " + dimensiune ); returnează un octet nou [ dimensiune ] ; } } /* Fațadă */ clasa Computer { private final static long BOOT_ADDRESS = 1L ; privat final static lung BOOT_SECTOR = 2L ; privat final static int SECTOR_SIZE = 3 ; CPU CPU privat ; memorie privată ; _ hard disk privat ; Public Computer () { this . cpu = CPU nou (); aceasta . memorie = memorie nouă (); aceasta . hardDrive = hard disk nou (); } public void startComputer () { cpu . congela (); memorie . încărcare ( BOOT_ADDRESS , hardDrive . citire ( BOOT_SECTOR , SECTOR_SIZE )); CPU . sari ( BOOT_ADDRESS ); CPU . executa (); } } /* Client */ class Application { public static void main ( String [] args ) { Computer computer = new Computer (); calculator . startComputer (); } }

haxe

Text sursă în limba Haxe /** * Implementări ale părților individuale ale computerului. * Fiecare metodă de clasă are un fel de implementare, în acest exemplu este omisă. */ /** * Class CPU, responsabil pentru funcționarea procesorului */ class CPU { public function new () { } înghețarea funcției publice (): Void { //... } salt de funcție publică ( poziția : Int ): Void { //... } funcția publică execute (): Void { //... } } /** * Class Memory, responsabilă pentru operarea memoriei */ class Memory { public static inline var BOOT_ADDRESS : Int = 0x0005 ; functie publica noua () { } încărcare funcție publică ( poziție : Int , date : haxe . io . Octeți ): Void { //... } } /** * Class HardDrive, responsabil pentru funcționarea hard diskului */ class HardDrive { public static inline var BOOT_SECTOR : Int = 0x001 ; public static inline var SECTOR_SIZE : Int = 64 ; functie publica noua () { } funcția publică citită ( lba : Int , dimensiune : Int ): haxe . io . Bytes { //... returnează null ; } } /** * Un exemplu de model „Fațadă” * Computerul este folosit ca obiect unificat. * În spatele acestui obiect vor fi ascunse, toate detaliile lucrării părților sale interne. */ class Computer { private var cpu : CPU ; private var memorie : Memorie ; private var hardDrive : HardDrive ; /** * Constructor de computer. * Initialize parts */ public function new () { this . cpu = CPU nou (); aceasta . memorie = memorie nouă (); aceasta . hardDrive = hard disk nou (); } /** * Gestionarea simplificată a comportamentului „pornire computer” */ public function startComputer (): Void { cpu . congela (); memorie . încărcare ( Memory . BOOT_ADDRESS , hardDrive . read ( HardDrive . BOOT_SECTOR , HardDrive . SECTOR_SIZE ) ); CPU . sari ( Memory.BOOT_ADDRESS ) ; _ CPU . executa (); } } /** * Utilizatorii de computere au la dispoziție o fațadă (computer) * care ascunde toată complexitatea lucrului cu componente individuale. */ class Application { public static function main (): Void { var computer : Computer = new Computer (); calculator . startComputer (); } }

Swift

Cod sursă rapid // Clasa logica CPU { public func freeze () -> String { return "Înghețare procesor." } public func jump ( poziție : șir ) -> șir { return "Sărit la: \( poziție ) " } public func execute () -> String { return "În executare." } } clasa Memorie { public func load ( poziție : șir , date : șir ) -> șir { return " Se încarcă din \( poziție ) date: \( date ) " } } clasa hard disk { public func read ( lba : String , size : String ) -> String { return "Unele date din sectorul \( lba ) cu dimensiunea \( size ) " } } // Clasa fațadă ComputerFacade { private let cpu = CPU () private let memorie = Memorie () private let hardDrive = HardDrive () public func start () { cpu . freeze () let ssd = hard disk . citire ( lba : „100” , dimensiune : „1024” ) memorie . încărcare ( poziție : "0x00" , date : ssd ) CPU . sări ( poziție : "0x00" ) CPU . executa () } } // Client let pc = ComputerFacade () pc . începe ()

Literatură

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tehnici de proiectare orientată pe obiecte. Design Patterns = Design Patterns: Elements of Reusable Object-Oriented Software. - Sankt Petersburg. : " Petru ", 2007. - S. 366. - ISBN 978-5-469-01136-1 . (și ISBN 5-272-00355-1 )

Surse și link-uri