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 .
Fasad
Fasad
Sorts strukturell
Beskrivs i Design Patterns Ja

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 med TComputer ( aDevice ) börja PlugIn ; _ PowerMonitor ; makt ; slut ; om aDevice är TNotebook med TNotebook ( aDevice ) gör Power ; om aDevice är TKettle 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