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 .
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