Fasad (designmönster)
Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från
versionen som granskades den 4 juli 2020; kontroller kräver
5 redigeringar .
Fasadmönstret ( eng. Fasad ) är ett strukturellt designmönster som låter dig dölja komplexiteten i systemet genom att reducera alla möjliga externa anrop till ett objekt , delegera dem till motsvarande objekt i systemet.
Beskrivning
Problem
Hur tillhandahåller man ett enhetligt gränssnitt med en uppsättning olika implementeringar eller gränssnitt, till exempel till ett delsystem, om stark koppling till det delsystemet inte är önskvärt, eller om implementeringen av delsystemet kan förändras?
Lösning
Definiera en interaktionspunkt med delsystemet - ett fasadobjekt som ger ett gemensamt gränssnitt med delsystemet, och anförtro det ansvaret för att interagera med dess komponenter. En fasad är ett externt objekt som tillhandahåller en enda ingångspunkt för delsystemtjänster. Implementeringen av andra delsystemkomponenter är privat och inte synlig för externa komponenter. Fasadobjekt tillhandahåller GRASP-implementering av mönstret Protected Variations när det gäller skydd mot förändringar i implementeringen av delsystemet.
Funktioner i programmet
En mall används för att ställa in någon sorts policy på en annan grupp av objekt. Om policyn ska vara ljus och märkbar bör du använda tjänsterna i Fasadmallen. Om det är nödvändigt att tillhandahålla sekretess och noggrannhet (transparens) är proxymönstret ett lämpligare val .
Exempel
C++
Källtext i
C++
#include <iostream>
#inkludera <sträng>
#inkludera <minne>
#inkludera <string_view>
/** Abstrakt musiker - inte en obligatorisk del av mönstret, introducerad för att förenkla koden */
klass musiker {
const char * namn ;
offentliga :
Musiker ( std :: string_viewname ) { _
detta -> namn = namn . data ();
}
virtuell ~ Musiker () = default ;
skyddad :
void output ( std :: string_view text ) {
std :: cout << detta -> namn << "" << text << "." << std :: endl ;
}
};
/** Specifika musiker */
klass sångare : offentlig musiker {
offentliga :
Vokalist ( std :: string_view name ) : Musiker ( namn ) {}
void singCouplet ( int coupletNumber ) {
std :: string text = "sång vers #" ;
text += std :: till_sträng ( coupletNumber );
output ( text );
}
void singChorus () {
output ( "sjung refrängen" );
}
};
klass gitarrist : offentlig musiker {
offentliga :
Gitarrist ( std :: string_view name ) : Musiker ( namn ) {}
void playCoolOpening () {
output ( "börjar med ett coolt intro" );
}
void playCoolRiffs () {
output ( "spelar coola riff" );
}
void playAnotherCoolRiffs () {
output ( "spelar andra coola riff" );
}
void playIncrediblyCoolSolo () {
output ( "lägger ut ett otroligt coolt solo" );
}
void playFinalAccord () {
output ( "avslutar låten med ett kraftfullt ackord" );
}
};
klass basist : offentlig musiker {
offentliga :
Basist ( std :: string_view name ) : Musiker ( namn ) {}
void followTheDrums () {
output ( "följer hjulen" );
}
void changeRhythm ( std :: string_viewtype ) { _
std :: string text = ( "växlade till rytm" );
text += typ ;
text += "a" ;
output ( text );
}
void stopPlaying () {
output ( "slutar spela" );
}
};
klass Trummis : offentlig musiker {
offentliga :
Trummis ( std :: string_view name ) : Musiker ( namn ) {}
void startPlaying () {
output ( "börjar spela" );
}
void stopPlaying () {
output ( "slutar spela" );
}
};
/** Fasad, i detta fall ett känt rockband */
klass BlackSabbath {
std :: unique_ptr < Vokalist > sångare ;
std :: unik_ptr < Gitarrist > gitarrist ;
std :: unik_ptr < Basist > basist ;
std :: unique_ptr < Trummis > trummis ;
offentliga :
BlackSabbath () {
vokalist = std :: make_unique < Vokalist > ( "Ozzy Osbourne" );
gitarrist = std :: make_unique < Gitarrist > ( "Tony Iommi" );
basist = std :: make_unique < Basist > ( "Geezer Butler" );
trummis = std :: make_unique < Trummis > ( "Bill Ward" );
}
void playCoolSong () {
gitarrist -> playCoolOpening ();
trummis -> börja spela ();
basist -> followTheDrums ();
gitarrist -> playCoolRiffs ();
sångare -> singCouplet ( 1 );
basist -> changeRhythm ( "refräng" );
gitarrist -> playAnotherCoolRiffs ();
sångare -> singChorus ();
basist -> changeRhythm ( "vers" );
gitarrist -> playCoolRiffs ();
sångare -> singCouplet ( 2 );
basist -> changeRhythm ( "refräng" );
gitarrist -> playAnotherCoolRiffs ();
sångare -> singChorus ();
basist -> changeRhythm ( "vers" );
gitarrist -> spela IncrediblyCoolSolo ();
gitarrist -> playCoolRiffs ();
sångare -> singCouplet ( 3 );
basist -> changeRhythm ( "refräng" );
gitarrist -> playAnotherCoolRiffs ();
sångare -> singChorus ();
basist -> changeRhythm ( "vers" );
gitarrist -> playCoolRiffs ();
basist -> stopPlaying ();
trummis -> stopPlaying ();
gitarrist -> playFinalAccord ();
}
};
int main () {
std :: cout << "OUTPUT:" << std :: endl ;
BlackSabbath band ;
band . playCoolSong ();
returnera 0 ;
}
/**
* OUTPUT:
* Tony Iommi börjar med ett coolt intro.
* Bill Ward börjar spela.
* Geezer Butler följer trummorna.
* Tony Iommi spelar fantastiska riff.
* Ozzy Osbourne sjöng vers #1.
* Geezer Butler bytte till körrytm.
* Tony Iommi spelar andra coola riff.
* Ozzy Osbourne sjöng refrängen.
* Geezer Butler bytte till versens rytm.
* Tony Iommi spelar fantastiska riff.
* Ozzy Osbourne sjöng vers #2.
* Geezer Butler bytte till körrytm.
* Tony Iommi spelar andra coola riff.
* Ozzy Osbourne sjöng refrängen.
* Geezer Butler bytte till versens rytm.
* Tony Iommi levererar ett otroligt coolt solo.
* Tony Iommi spelar fantastiska riff.
* Ozzy Osbourne sjöng vers #3.
* Geezer Butler bytte till körrytm.
* Tony Iommi spelar andra coola riff.
* Ozzy Osbourne sjöng refrängen.
* Geezer Butler bytte till versens rytm.
* Tony Iommi spelar fantastiska riff.
* Geezer Butler slutar spela.
* Bill Ward slutar spela.
* Tony Iommi avslutar låten med ett kraftfullt ackord.
*/
JavaScript
JavaScript -källkod
/* Komplexa delar */
function SubSystem1 () {
this . metod1 = funktion () {
konsol . log ( "SubSystem1.metod1 anropad" );
};
}
function SubSystem2 () {
this . metod2 = funktion () {
konsol . log ( "SubSystem2.metod2 anropad" );
};
detta . metodB = funktion () {
konsol . log ( "SubSystem2.metodB anropad" );
};
}
/* Fasad */
function Facade () {
var s1 = new SubSystem1 (),
s2 = new SubSystem2 ();
detta . m1 = funktion () {
konsol . log ( "Facade.m1 kallas" );
s1 . metod1 ();
s2 . metod2 ();
};
detta . m2 = funktion () {
konsol . log ( "Facade.m2 kallas" );
s2 . metodB ();
};
}
/* Klient */
funktionstest ( ) { var fasad = ny fasad (); fasad . ml (); fasad . m2 (); }
test ();
/*
Utdata:
"Facade.m1 kallas"
"SubSystem1.metod1 kallas"
"SubSystem2.metod2 kallas"
"Facade.m2 kallas"
"SubSystem2.metodB kallas"
*/
CoffeeScript
Källtext på
CoffeeScript- språket
# Image loader
class ImageLoader
loadImage = (src) ->
# ...
konstruktor: (hash = {}) ->
@images = {}
@images [ namn ] = ladda Bild ( src ) för namn , src av hash
# Audio loader
class SoundLoader
loadSound = (src) ->
# ...
konstruktor: (hash = {}) ->
@sounds = {}
@sounds [ namn ] = loadSound ( src ) för namn , src av hash
# Fasadklass
Loader- konstruktör
: ({bilder, ljud}) ->
@images = ny ImageLoader ( bilder ). bilder
@sounds = ny SoundLoader ( ljud ). ljud
ljud : (namn) ->
@ljud [ namn ]
bild : (namn) ->
@bilder [ namn ]
PHP
PHP källkod
/**
* Implementeringar av enskilda datordelar.
* Varje klassmetod har någon form av implementering, i detta exempel är den utelämnad.
*/
/**
* Klass CPU, ansvarig för att köra CPU
*/
klass CPU
{
public function freeze () {}
public function jump ( $position ) {}
public function execute () {}
}
/**
* Klassminne, ansvarig för minnesdrift
*/
klass Minne
{
const BOOT_ADDRESS = 0x0005 ;
offentlig funktionsladdning ( $ position , $data ) {} }
/**
* Klass hårddisk, ansvarig för hårddiskdrift
*/
klass hårddisk
{
const BOOT_SECTOR = 0x001 ;
const SECTOR_SIZE = 64 ;
public function read ( $lba , $size ) {}
}
/**
* Ett exempel på "Fasad"-mönstret
* Datorn används som ett enhetligt objekt.
* Bakom detta objekt kommer att döljas alla detaljer om arbetet med dess interna delar.
*/
class Computer
{
protected $cpu ;
skyddat $minne ;
skyddad $hårddisk ;
/**
* Datorkonstruktör.
* Initiera delar
*/
public function __construct ()
{
$this -> cpu = new CPU ();
$this -> minne = nytt minne ();
$this -> hårddisk = ny hårddisk ();
}
/**
* Förenklad hantering av "datorstart" beteende
*/
public function startComputer ()
{
$cpu = $this -> cpu ;
$minne = $detta -> minne ;
$hardDrive = $this -> hårddisk ;
$cpu -> frys ();
$memory -> ladda (
$memory :: BOOT_ADDRESS ,
$hardDrive -> read ( $hardDrive :: BOOT_SECTOR , $hardDrive :: SECTOR_SIZE )
);
$cpu -> jump ( $minne :: BOOT_ADDRESS );
$cpu -> exekvera ();
}
}
/**
* Datoranvändare förses med en Fasad (dator)
* som döljer all komplexiteten i att arbeta med enskilda komponenter.
*/
$dator = ny dator ();
$dator -> startComputer ();
Python
Källkod i
Python
# Komplexa delar av systemklassen
CPU ( objekt ) :
def __init__ ( self ):
# ...
pass
def freeze ( self ):
# ...
pass
def jump ( själv , adress ):
# ...
pass
def execute ( self ):
# ...
pass
klass Minne ( objekt ):
def __init__ ( själv ):
# ...
pass
def load ( själv , position , data ):
# ...
pass
klass Hårddisk ( objekt ):
def __init__ ( själv ):
# ...
pass
def read ( self , lba , size ):
# ...
pass
# Fasadklass
Dator ( objekt ) :
def __init__ ( själv ):
själv . _cpu = cpu ()
själv . _memory = Minne ()
själv . _hårddisk = hårddisk ()
def startDator ( själv ):
själv . _cpu . frysa ()
själv . _minne . ladda ( BOOT_ADDRESS , self . _hardDrive . read ( BOOT_SECTOR , SECTOR_SIZE ))
self . _cpu . hoppa ( BOOT_ADDRESS )
själv . _cpu . exekvera ()
# Klientsida
om __name__ == "__main__" :
fasad = Dator ()
fasad . starta dator ()
C#
Källtext i
C#
använder System ;
namnområde Bibliotek
{
/// <summary>
/// Subsystem class
/// </summary>
/// <remarks>
/// <li>
/// <lu>implementerar subsystemfunktioner;</lu>
/// <lu>gör det arbete som tilldelats av objektet <see cref="Facade"/>;</lu>
/// <lu>vet inte något om fasadens existens, det vill säga den lagrar inte referenser till det;</lu>
/ // </li>
/// </remarks>
intern klass SubsystemA
{
intern sträng A1 ()
{
return "Subsystem A, Method A1\n" ;
}
intern sträng A2 ()
{
return "Subsystem A, Method A2\n" ;
}
}
intern klass UndersystemB
{
intern sträng B1 ()
{
return "Subsystem B, metod B1\n" ;
}
}
intern klass SubsystemC
{
intern sträng C1 ()
{
return "Subsystem C, Method C1\n" ;
}
}
}
/// <sammanfattning>
/// Fasad - fasad
/// </summary>
/// <remarks>
/// <li>
/// <lu>"vet" vilka undersystemsklasser som ska adresseras förfrågan med;< /lu >
/// <lu>delegera klientförfrågningar till lämpliga objekt inom undersystemet;</lu>
/// </li>
/// </remarks>
public class Facade
{
Library . SubsystemA a = nytt bibliotek . SubsystemA ();
bibliotek . SubsystemB b = nytt bibliotek . SubsystemB ();
bibliotek . SubsystemC c = nytt bibliotek . SubsystemC ();
public void Operation1 ()
{
Console . WriteLine ( "Operation 1\n" +
a . A1 () +
a . A2 () +
b . B1 ());
}
public void Operation2 ()
{
Console . WriteLine ( "Operation 2\n" +
b . B1 () +
c . C1 ());
}
}
klass Program
{
static void Main ( string [] args )
{
Fasadfasad = ny Fasad ( );
fasad . Operation1 ();
fasad . Operation2 ();
// Vänta på
användarkonsolen . läs ();
}
}
Ruby
Källtext på
rubinspråk
modul Bibliotek
# <summary>
# Subsystem class
# </summary>
# <remarks>
# <li>
# <lu>implementerar subsystemfunktionalitet;</lu>
# <lu>gör jobbet som tilldelats av <see cref="Facade"/> ;</lu>
# <lu>vet inte något om fasadens existens, det vill säga den lagrar inga referenser till den;</lu>
# </li>
# </remarks>
class SubsystemA
def a1 ; "Subsystem A, metod a1 \n " ; enddef
a2 ; _ "Subsystem A, metod a2 \n " ; slutändan _
klass SubsystemB
def b1 ; "Subsystem B, metod b1 \n " ; slutändan
_
klass SubsystemC
def c1 ; "Subsystem C, metod c1 \n " ; slut
ände
_
# <summary>
# Fasad
# </summary>
# <remarks>
# <li>
# <lu>"vet" vilka undersystemklasser som ska adresseras förfrågningar till;</lu>
# <lu>delegerar förfrågningar till klienter till lämpliga objekt inom delsystemet ;</lu>
# </li>
# </remarks>
klass Fasad
def initialize
@a = Bibliotek :: SubsystemA . ny ;
@b = Bibliotek :: SubsystemB . ny ;
@c = Bibliotek :: SubsystemC . ny ;
slutet
def operation1
sätter "Operation 1 \n " +
@a . a1 +
@a . a2 +
@b . b1
slutet
def operation2
sätter "Operation 2 \n " +
@b . b1 () +
@c . c1 (
) slutände
fasad = fasad . ny
fasad . drift1
fasad . operation2
# Vänta på att användaren
får
VB.NET
Källtext på språket
VB.NET
Namnområdesbibliotek _
'Subsystemklass
'. implementerar delsystemets funktionalitet
”. utför det arbete som tilldelas av Fasadobjektet
'. "vet" ingenting om fasadens existens, det vill säga den lagrar inga referenser till den
Friend Class SubsystemA
Friend Funktion A1 () Som String
Return "Subsystem A, Method A1" & vbCrLf
End Function
Friend Funktion A2 () Som String
Return "Subsystem A, Method A2" & vbCrLf
End Function
End Class
Friend Class SubsystemB
Friend Funktion B1 () Som String
Return "Subsystem B, Method B1" & vbCrLf
End Function
End Class
Friend Class SubsystemC
Friend Function C1 () Som String
Return "Subsystem C, Method C1" & vbCrLf
End Function
End Class
avsluta namnutrymmet
'Fasad
'. "vet" vilka undersystemsklasser som ska hantera begäran
' . delegerar klientförfrågningar till lämpliga objekt inom undersystemet
Public NotInheritable Class Facade
Private Sub New ()
End Sub
Delade ett som nytt bibliotek . DelsystemA ()
Delat b Som nytt bibliotek . DelsystemB ()
Delat c Som nytt bibliotek . SubsystemC ()
Offentlig delad underdrift1 ( )
konsol . WriteLine ( "Operation 1" & vbCrLf & a . A1 () & a . A2 () & b . B1 ()) End Sub
Offentlig delad underdrift2 ( )
konsol . WriteLine ( "Operation 2" & vbCrLf & b . B1 () & c . C1 ())
End Sub
End Class
klassprogram _
Delad Sub Main ()
Fasad . Drift1 ()
Fasad . Operation2 ()
"Väntar på
användaråtgärdskonsol . Läs ()
End Sub
End Class
Delphi
Källtext i
Delphi
program Fasadmönster ;
{$APPTYPE KONSOL}
använder
SysUtils ;
typ
TComputer = klass
offentlig
procedur PlugIn ;
procedur PowerMonitor ;
procedur Power ;
slut ;
procedur TComputer . Plugga in ;
begin
WriteLn ( 'Inkluderad i nätverket' ) ;
slut ;
procedur TComputer . PowerMonitor ;
börja
WriteLn ( 'Slå på monitorn' ) ;
slut ;
procedur TComputer . makt ;
begin
WriteLn ( 'Vrid systemenheten' ) ;
slut ;
typ
TNotebook = klassprocedur
Power ; _ slut ;
procedur TAnteckningsbok . makt ;
börja
WriteLn ( 'Tryck på strömknappen' ) ;
slut ;
typ
TKettle = klassprocedur
PlugIn ; _ procedur Power ; slut ;
procedur TKettle . makt ;
börja
WriteLn ( 'Tryck på strömknappen' ) ;
slut ;
procedur TKettle . Plugga in ;
begin
WriteLn ( 'Inkluderad i nätverket' ) ;
slut ;
typ
TFacade = klass
offentlig
procedur PowerOn ( aDevice : TObject ) ;
slut ;
förfarande TFacade . PowerOn ( aDevice : TObject ) ;
börja
om aDevice är TComputer så
med TComputer ( aDevice ) börja PlugIn ; _
PowerMonitor ; makt ; slut ;
om aDevice är TNotebook så
med TNotebook ( aDevice ) gör
Power ;
om aDevice är TKettle så
börjar PlugIn med TKettle ( aDevice ) ; _ makt ; slut ;
SkrivLn
slut ;
börja
med TFacade . Skapa prova PowerOn
( TComputer . Skapa ) ; _ PowerOn ( TNotebook.Create ) ; _ _ PowerOn ( TKettle.Create ) ; _ _ slutligen Gratis ; slut ; Läsln ; slut .
Java
Java -källa
/* Komplexa delar */
klass CPU {
public void freeze () {
System . ut . println ( "frysa" );
}
public void jump ( lång position ) {
System . ut . println ( "hoppposition = " + position );
}
public void execute () {
System . ut . println ( "exekvera" );
}
}
class Memory {
public void load ( lång position , byte [] data ) {
System . ut . println ( "load position = " + position + ", data = " + data );
}
}
class HardDrive {
public byte [] read ( long lba , int size ) {
System . ut . println ( "läs lba = " + lba + ", storlek = " + storlek );
returnera ny byte [ storlek ] ;
}
}
/* Fasad */
class Computer {
private final static long BOOT_ADDRESS = 1L ;
privat slutlig statisk lång BOOT_SECTOR = 2L ;
privat slutlig statisk int SECTOR_SIZE = 3 ;
privat CPU -processor ;
privat minne ; _ privat hårddisk hårddisk ;
offentlig dator () {
detta . cpu = ny cpu ();
detta . minne = nytt minne ();
detta . hårddisk = ny hårddisk ();
}
public void startComputer () {
cpu . frysa ();
minne . ladda ( BOOT_ADDRESS , hårddisk . läs ( BOOT_SECTOR , SECTOR_SIZE ));
cpu . jump ( BOOT_ADDRESS );
cpu . exekvera ();
}
}
/* Klient */
class Application {
public static void main ( String [] args ) {
Dator dator = ny dator ();
dator . starta dator ();
}
}
haxe
Källtext på
Haxe-språk
/**
* Implementeringar av enskilda datordelar.
* Varje klassmetod har någon form av implementering, i detta exempel är den utelämnad.
*/
/**
* Klass CPU, ansvarig för driften av processorn
*/
klass CPU {
public function new () {
}
frysning av offentliga funktioner (): Void { //... }
public function jump ( position : Int ): Void {
//...
}
public function execute (): Void {
//...
}
}
/**
* Klassminne, ansvarig för minnesdrift
*/
klass Memory {
public static inline var BOOT_ADDRESS
: Int = 0x0005 ;
offentlig funktion ny () {
}
offentlig funktionsbelastning ( position : Int , data : haxe . io . Bytes ) : Void { //... } }
/**
* Klass hårddisk, ansvarig för hårddiskdrift
*/
klass hårddisk {
public static inline var BOOT_SECTOR
: Int = 0x001 ;
public static inline var SECTOR_SIZE
: Int = 64 ;
offentlig funktion ny () {
}
offentlig funktion läst ( lba : Int , storlek : Int ): haxe . io . Bytes {
//...
returnerar null ;
}
}
/**
* Ett exempel på "Fasad"-mönstret
* Datorn används som ett enhetligt objekt.
* Bakom detta objekt kommer att döljas, alla detaljer om arbetet med dess interna delar.
*/
class Computer {
private var cpu
: CPU ;
private var memory
: Memory ;
privat var hårddisk
: hårddisk ;
/**
* Datorkonstruktör.
* Initiera delar
*/
offentlig funktion ny () {
detta . cpu = ny cpu ();
detta . minne = nytt minne ();
detta . hårddisk = ny hårddisk ();
}
/**
* Förenklad hantering av "datorstart" beteende
*/
public function startComputer (): Void {
cpu . frysa ();
minne . ladda (
Minne . BOOT_ADDRESS ,
hårddisk . läst ( Hårddisk . BOOT_SECTOR , hårddisk . SECTOR_SIZE )
);
cpu . jump ( Memory.BOOT_ADDRESS ) ; _ cpu . exekvera (); } }
/**
* Datoranvändare förses med en Fasad (dator)
* som döljer all komplexiteten i att arbeta med enskilda komponenter.
*/
class Application {
public static function main (): Void {
var computer
: Computer = new Computer ();
dator . startDator ();
}
}
Swift
Swift källkod
//
Logikklass CPU {
public func freeze () -> String {
return "Freezing processor."
}
public func jump ( position : String ) -> String {
return "Hoppa till: \( position ) "
}
public func execute () -> String {
return "Executing."
}
}
klass Minne {
public func load ( position : String , data : String ) -> String {
return "Loading from \( position ) data: \( data ) "
}
}
klass hårddisk {
public func read ( lba : String , size : String ) -> String {
return "Vissa data från sektor \( lba ) med storlek \( storlek ) "
}
}
//
Fasadklass ComputerFacade {
privat låt cpu = CPU ()
privat låt minne = Minne ()
privat låt hårddisk = Hårddisk ()
public func start () {
cpu . frys ()
låt ssd = hårddisk . läs ( lba : "100" , storlek : "1024" )
minne . ladda ( position : "0x00" , data : ssd )
cpu . hoppa ( position : "0x00" )
cpu . exekvera ()
}
}
// Client
let pc = ComputerFacade ()
pc . börja ()
Litteratur
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tekniker för objektorienterad design. Designmönster = Designmönster: Element av återanvändbar objektorienterad programvara. - St Petersburg. : " Peter ", 2007. - S. 366. - ISBN 978-5-469-01136-1 . (även ISBN 5-272-00355-1 )
Källor och länkar