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