Pod (model de design)

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită la 9 martie 2016; verificările necesită 11 modificări .
Pod
Pod
Tip de structural
Descris în Design Patterns da

Modelul de punte este un model de proiectare structurală  utilizat în proiectarea software pentru a „separa abstracția și implementarea , astfel încât acestea să se poată schimba independent”. Modelul punte folosește încapsularea , agregarea și poate folosi moștenirea pentru a împărți responsabilitățile între clase.

Scop

Când o clasă se schimbă frecvent, avantajele abordării orientate pe obiecte devin foarte utile, permițându-vă să faceți modificări programului cu cunoștințe minime despre implementarea programului. Modelul bridge este util acolo unde nu numai clasa în sine se schimbă frecvent, ci și ceea ce face.

Descriere

Când abstracția și implementarea sunt separate, ele se pot schimba independent. Cu alte cuvinte, atunci când este implementată prin modelul de punte, modificarea structurii interfeței nu interferează cu schimbarea structurii implementării. Considerați o astfel de abstractizare ca o figură. Există multe tipuri de forme, fiecare cu proprietățile și metodele sale. Cu toate acestea, există ceva care unește toate figurile. De exemplu, fiecare formă trebuie să fie capabilă să se deseneze singură, să se scaleze etc. În același timp, desenele grafice pot diferi în funcție de tipul de sistem de operare sau de biblioteca grafică. Formele trebuie să fie capabile să se deseneze în diferite medii grafice, dar este imposibil să implementați toate metodele de desenare în fiecare formă sau să modificați forma de fiecare dată când metoda de desenare se schimbă. În acest caz, modelul de punte ajută, permițându-vă să creați noi clase care vor implementa desenul în diverse medii grafice. Folosind această abordare, este foarte ușor să adăugați atât forme noi, cât și modalități de a le desena.

Legătura reprezentată de săgeată în diagrame poate avea 2 semnificații: a) „un fel”, în conformitate cu principiul substituției Liskov, și b) una dintre posibilele implementări ale abstractizării. Limbile folosesc de obicei moștenirea pentru a implementa atât a) cât și b), ceea ce tinde să umfle ierarhiile de clasă.

Puntea servește tocmai la rezolvarea acestei probleme: obiectele sunt create în perechi dintr-un obiect din clasa ierarhiei A și ierarhiei B, moștenirea în cadrul ierarhiei A are sensul de „variantă” conform lui Liskov, iar pentru conceptul de „ implementarea abstracției” se folosește o legătură de la obiectul A la obiectul său pereche B.

Utilizare

Arhitectura Java AWT se bazează în întregime pe acest model - ierarhia java.awt.xxx pentru handle și sun.awt.xxx pentru implementări.

Exemple

Exemplu C++

Text sursă în C++ #include <iostream> folosind namespace std ; sertar clasa { public : virtual void drawCircle ( int x , int y , int radius ) = 0 ; }; clasa SmallCircleDrawer : public Drawer { public : const double razăMultiplicator = 0,25 ; void drawCircle ( int x , int y , int radius ) suprascrie { cout << "Centrul cercului mic " << x << ", " << y << " raza = " << radius * radiusMultiplier << endl ; } }; clasa LargeCircleDrawer : public Drawer { public : const double razăMultiplicator = 10 ; void drawCircle ( int x , int y , int radius ) suprascrie { cout << "Centrul cercului mare" << x << ", " << y << " raza = " << radius * radiusMultiplier << endl ; } }; Class Shape { protejat : Sertar * sertar ; public : Forma ( sertar * drw ) { sertar = drw ; } forma () {} virtual void draw () = 0 ; virtual void enlargeRadius ( multiplicator int ) = 0 ; }; clasa Cerc : public Shape { int x , y , raza ; public : Cerc ( int _x , int _y , int _radius , Sertar * drw ) { sertar = drw ; setX ( _x ); setY ( _y ); setRadius ( _raza ); } void draw () override { sertar -> drawCircle ( x , y , raza ); } void enlargeRadius ( multiplicator int ) override { raza *= multiplicator ; } void setX ( int_x ) { _ x = _x ; } void setY ( int_y ) { _ y = _y _ } void setRadius ( int _raza ) { raza = _raza ; } }; int main ( int argc , char * argv []) { Formă * forme [ 2 ] = { Cerc nou ( 5 , 10 , 10 , nou LargeCircleDrawer ()), nou Cerc ( 20 , 30 , 100 , nou SmallCircleDrawer ())}; pentru ( int i = 0 ; i < 2 ; i ++ ) { forme [ i ] -> desen (); } returnează 0 ; } // Ieșire Centrul cerc mare = 5 , 10 rază = 100 Centrul cercului mic = 20 , 30 raza = 25,0

Exemplu Java

Sursa Java interfață publică sertar { public void drawCircle ( int x , int y , int radius ); } Clasa publică SmallCircleDrawer implementează Sertar { public static final dublu razăMultiplicator = 0,25 ; @Override public void drawCircle ( int x , int y , int radius ) { System . afară . println ( "Centrul cercului mic = " + x + "," + y + " raza = " + raza * raza Multiplicator ); } } clasă publică LargeCircleDrawer implementează Sertar { public static final int radiusMultiplier = 10 ; @Override public void drawCircle ( int x , int y , int radius ) { System . afară . println ( "Centrul cercului mare = " + x + "," + y + " raza = " + raza * raza Multiplicator ); } } clasa public abstract Shape { sertar sertar protejat ; protected Shape ( Drawer drawer ){ this . sertar = sertar ; } extragere public abstract void (); public abstract void enlargeRadius ( multiplicator int ); } clasă publică Cercul se extinde Forma { privat int x ; private int y ; private int radius ; public Circle ( int x , int y , int radius , Drawer drawer ) { super ( drawer ); setX ( x ); setY ( y ); setRadius ( raza ); } @Override public void draw () { sertar . drawCircle ( x , y , raza ); } @Override public void enlargeRadius ( int multiplicator ) { radius *= multiplicator ; } public int getX () { return x ; } public int getY () { return y ; } public int getRadius () { return raza ; } public void setX ( int x ) { this . x = x ; } public void setY ( int y ) { this . y = y _ } public void setRadius ( rază int ) { this . raza = raza ; } } // Clasă care arată cum funcționează modelul de design „Pont”. Aplicație de clasă publică { public static void main ( String [] args ){ Shape [] shapes = { new Circle ( 5 , 10 , 10 , new LargeCircleDrawer ()), new Circle ( 20 , 30 , 100 , new SmallCircleDrawer ())}; pentru ( Shape next : shapes ) next . trage (); } } // Ieșire Centru cerc mare = 5 , 10 rază = 100 Centru cerc mic = 20 , 30 rază = 25,0

Exemplu în C#

Text sursă în C# folosind System ; namespace Bridge { // Aplicația de testare MainApp class MainApp { static void Main () { Abstraction ab = new RefinedAbstraction (); // Setați implementarea și apelați ab . Implementor = nou ConcreteImplementorA (); ab . operațiuni (); // Schimbați implementarea și apelați ab . Implementor = nou ConcreteImplementorB (); ab . operațiuni (); // Așteptați Consola utilizatorului . citește (); } } /// <summary> /// Abstraction - abstraction /// </summary> /// <remarks> /// <li> /// <lu>definiți interfața de abstractizare;</lu> /// < lu >stochează o referință la un obiect <see cref="Implementor"/></lu> /// </li> /// </remarks> class Abstraction { // Proprietate public Implementor Implementor { get ; set ; } public virtual void Operațiune () { Implementator . operațiuni (); } } /// <summary> /// Implementor /// </summary> /// <remarks> /// <li> /// <lu> definește o interfață pentru clasele de implementare. Nu trebuie /// să se potrivească exact cu interfața clasei <see cref="Abstraction"/>. De fapt, ambele /// interfețe pot fi complet diferite. De obicei, interfața de clasă /// <see cref="Implementor"/> reprezintă doar operații primitive, în timp ce clasa /// <see cref="Abstraction"/> definește operațiuni de nivel superior /// pe baza acestor primitive; <// lu> /// </li> /// </remarks> abstract class Implementor { public abstract void Operation (); } /// <summary> /// RefinedAbstraction /// </summary> /// <remarks> /// <li> /// <lu>extinde interfața definită de abstracția <see cref="Abstraction" / ></lu> /// </li> /// </remarks> class RefinedAbstraction : Abstraction { public override void Operation () { Implementor . operațiuni (); } } /// <summary> /// ConcreteImplementor - implementator concret /// </summary> /// <remarks> /// <li> /// <lu>conține implementarea concretă a interfeței <see cref="Implementor" / ></lu> /// </li> /// </remarks> class ConcreteImplementorA : Implementor { public override void Operation () { Console . WriteLine ( "Operațiunea de implementare a betonului" ); } } // "ConcreteImplementorB" class ConcreteImplementorB : Implementor { public override void Operation () { Consola . WriteLine ( "Operațiunea ConcreteImplementorB" ); } } }

Exemplu PHP5

Cod sursă PHP5 interfață IPrinter { public function printHeader ( $textHeader ); funcția publică printBody ( $textBody ); } class PdfPrinter implementează IPrinter { public function printHeader ( $textHeader ) { echo 'Acesta este antetul tău (' . $textHeader . ') în fișierul pdf<br>' ; } public function printBody ( $textBody ) { echo 'Acesta este corpul tau text (' . $textBody . ') in fisierul pdf<br>' ; } } class ExcelPrinter implementează IPrinter { public function printHeader ( $textHeader ) { echo 'Acesta este antetul tău (' . $textHeader . ') în fișierul xls<br>' ; } public function printBody ( $textBody ) { echo 'Acesta este corpul tau de text (' . $textBody . ') in fisierul xls<br>' ; } } clasa abstracta Raport { protected $printer ; function public __construct ( IPrinter $printer ) { $this -> printer = $printer ; } public function printHeader ( $textHeader ) { $this -> printer -> printHeader ( $textHeader ); } public function printBody ( $textBody ) { $this -> printer -> printBody ( $textBody ); } } clasa Raport săptămânal extinde Raport { funcția publică print ( matrice $text ) { $this -> printHeader ( $text [ 'header' ]); $this -> printBody ( $text [ 'corp' ]); } } $raport = new WeeklyReport ( nou ExcelPrinter ()); $raport -> print ([ 'header' => 'antetul meu pentru excel' , 'body' => 'corpul meu pentru excel' ]); // Acesta este antetul tău (antetul meu pentru Excel) în fișierul xls</ br>Acesta este corpul tău text (corpul meu pentru Excel) în fișierul xls<br> $report = new WeeklyReport ( new PdfPrinter ()); $report -> print ([ 'header' => 'antetul meu pentru pdf' , 'body' => 'corpul meu pentru pdf' ]); // Acesta este antetul dvs. (antetul meu pentru pdf) în fișierul pdf</br>Acesta este corpul dvs. text (corpul meu pentru pdf) în fișierul pdf<br>

Exemplu PHP5.4

Textul sursă în PHP5.4 caracteristica TData { private $date ; function public __construct ( array $date ) { $this -> data = $date ; $aceasta -> pregăti (); } funcţie abstractă protejată pregăti (); } caracteristică TShow { private $conținut ; public function show () { print $this -> content ; } } clasa XmlFormat { folosește TData , TShow ; function protected prepare () { $this -> content = '<?xml version="1.1" encoding="UTF-8" ?><root>' ; foreach ( $this -> data as $name => $item ) { $this -> content .= "< $name > $item </ $name >" ; } $this -> content .= '</root>' ; } } clasa JsonFormat { folosește TData , TShow ; function protected prepare () { $this -> content = json_encode ( $this -> data ); } } clasa SelfFormat { folosește TData , TShow ; function protected prepare () { $content = array (); foreach ( $this -> data as $name => $item ) { $string = '' ; if ( is_string ( $nume )) { $nLen = strlen ( $nume ); $șir .= "[nume|șir( { $nLen } ){ { $nume } }:val|" ; } if ( is_int ( $nume )) { $șir .= "[index|int{ { $nume } }:val|" ; } if ( is_string ( $item )) { $vLen = strlen ( $item ); $șir .= "șir( $vLen ){ { $articol } " ; } if ( is_int ( $item )) { $string .= "int{ { $item } " ; } $șir .= "}]" ; array_push ( $conținut , $șir ); } $this -> content = 'selfMadeDataFormat:Array(' . count ( $this -> data ) . '):' ; $this -> content .= implode ( ',' , $content ); $this -> content .= ':endSelfMadeDataFormat' ; } } $xml = new XmlFormat ( matrice ( 'a' => 'b' , 'c' )); $json = nou JsonFormat ( array ( 'a' => 'b' , 'c' )); $self = nou SelfFormat ( array ( 'a' => 'b' , 'c' )); $self -> arata (); /* selfMadeDataFormat:Array(2):[nume|șir(1){a}:val|șir(1){b}],[index|int{0}:val|șir(1){c}]: endSelfMadeDataFormat */ $xml -> show (); /* <?xml version="1.1" encoding="UTF-8" ?><root><a>b</a><0>c</0></root> */ $json -> arată ( ); /* {"a":"b","0":"c"} */

Exemplu CoffeeScript

Text sursă în limbajul CoffeeScript # Clasa de implementare IStorage get : (cheie) -> set : (cheie, valoare) -> # Clasa ConcreteImplementor IFlashStorage extinde IStorage # ... # Clasa ConcreteImplementor IJavaStorage extinde IStorage # ... # Clasa ConcreteImplementor ISessionStorage extinde IStorage # ... # Clasa ConcreteImplementor ICookieStorage extinde IStorage # ... # Clasa ConcreteImplementor IGhostStorage extinde IStorage # ... # Clasa de abstractizare AStorage # protected _implementer : if sessionStorage new ISessionStorage else if navigator . pluginuri [ "Shockwave Flash" ] nou IFlashStorage else if navigator . javaEnabled () nou IJavaStorage altfel dacă navigator . cookieActivat nou ICookieStorage, altfel nou IGhostStorage # încărcare publică : (cheie) -> uitat : (cheie) -> salvare : (cheie, valoare) -> # Clasa RefinedAbstraction InfoStorage extinde AStorage load : (cheie) -> @_implementer . get ( "Informații: #{ cheie } " ) salvare : (cheie, valoare) -> @_implementer . set ( „Informații: #{ cheie } , valoare ) a uitat: (cheie) -> @_implementer . set ( „Informații: #{ cheie } , null )

Exemplu JavaScript

Cod sursă JavaScript // Implementator ("interfață") function Implementor () { this . functionare = function () {}; } // ConcreteImplementor (Implementator de implementare) function ConcreteImplementorA () { this . operation = function () { alert ( "ConcreteImplementorA.operation" ); }; } ConcreteImplementorA . prototip = Obiect . creați ( Implementator . prototip ); ConcreteImplementorA . prototip . constructor = ConcreteImplementorA ; function ConcreteImplementorB () { this . operation = function () { alert ( "ConcreteImplementorB.operation" ); }; } ConcreteImplementorB . prototip = Obiect . creați ( Implementator . prototip ); ConcreteImplementorB . prototip . constructor = ConcreteImplementorB ; // Funcția de abstracție Abstraction () { var implementor ; aceasta . getImplementor = function () { // accesarea implementorului din RefinedAbstraction return implementor ; }; aceasta . setImplementor = function ( val ) { implementor = val ; }; aceasta . operation = function () { implementator . operare (); }; } // RefinedAbstraction function RefinedAbstraction () { var abstr = new Abstraction (); aceasta . setImplementor = function ( val ) { abstr . setImplementor ( val ); }; aceasta . functionare = function () { abstr . operare (); }; } // utilizare: var refAbstr = new RefinedAbstraction (); refAbstr . setImplementor ( nou ConcreteImplementorA () ); refAbstr . operare (); // "Operațiunea ConcreteImplementorA." refAbstr . setImplementor ( nou ConcreteImplementorB () ); refAbstr . operare (); // "Operațiunea ConcreteImplementorB."

Fără a fi nevoie să supraîncărcați metodele de abstractizare, RefinedAbstraction poate fi foarte simplificată:

function RefinedAbstraction () { Abstracție . apel ( acesta ); }

De asemenea, puteți salva referințe la metode supraîncărcate imediat după ce Abstracția este instanțiată:

function RefinedAbstraction () { Abstracție . apel ( acesta ); var abstr_setImplementor = this . setImplementor ; aceasta . setImplementor = function ( val ) { abstr_setImplementor ( val ); }; }

Exemplu VB.NET

Text sursă în limba VB.NET punte de spațiu de nume ' Program - Test Application Class Program Shared Sub Main () Dim AB As Abstraction = New RefinedAbstraction () ' Instalați implementarea și apelați AB . Implementator = New ConcreteImplementorA () AB . operare () ' Instalați implementarea și apelați AB . Implementator = New ConcreteImplementorB () AB . operare () ' Așteptați acțiunea utilizatorului Consola . Citiți () End Sub End Class ''' <summary> ''' Abstraction - abstraction ''' </summary> ''' <remarks> ''' <li> ''' <lu>definiți interfața de abstractizare;</lu> ''' < lu >stochează o referință la un obiect <see cref="Implementor"/></lu> ''' </li> ''' </remarks> Abstracția clasei protejată m_implementor ca implementator ' Public Property Implementor () Ca implementator Get Return m_implementor End Get Set ( Valoare ByVal As Implementor ) m_implementor = valoare End Set End Proprietate Suboperație publică care poate fi anulată ( ) m_implementor . Operațiunea () End Sub End Class ''' <summary> ''' Implementator ''' </summary> ''' <remarks> ''' <li> ''' <lu> definește o interfață pentru clasele de implementare. Nu trebuie să se potrivească exact cu interfața clasei <see cref="Abstraction"/>. De fapt, ambele interfețe ''' pot fi complet diferite. De obicei, interfața de clasă ''' <vezi cref="Implementor"/> reprezintă doar operații primitive, iar clasa ''' <vezi cref="Abstraction"/> definește operațiuni de nivel superior bazate pe aceste primitive ''';< / lu> ''' </li> ''' </remarks> MustInherit Class Implementor Public MustOverride Sub Operation () End Class ''' <summary> ''' RefinedAbstraction - o abstractizare rafinată ''' </summary> ''' <remarks> ''' <li> ''' <lu> extinde interfața definită de abstracția <see cref= „Abstracție” /></lu> ''' </li> ''' </remarks> Clasa RefinedAbstraction moștenește abstracția Public Override Sub Operation () implementator . Operațiunea () End Sub End Class ''' <summary> ''' ConcreteImplementor - un implementator concret ''' </summary> ''' <remarks> ''' <li> ''' <lu>conține o implementare concretă a interfeței <vezi cref= „Implementator”/ ></lu> ''' </li> ''' </remarks> Clasa ConcreteImplementorA moștenește Implementor Consola de suboperație () de anulări publice . WriteLine ( "ConcreteImplementorA Operation" ) End Sub End Class Clasa „ConcreteImplementorB” ConcreteImplementorB moștenește Implementor Consola de suboperație () de anulări publice . WriteLine ( "ConcreteImplementorB Operation" ) End Sub End Class End Namespace

Exemplu Python

Cod sursă în Python # Clasa de implementare DrawingAPI : def drawCircle ( self , x , y , radius ): trece # ConcreteImplementor 1/2 class DrawingAPI1 ( DrawingAPI ): def drawCircle ( self , x , y , radius ): tipăriți „API1.circle at %f : %f radius %f % ( x , y , radius ) # ConcreteImplementor 2/2 class DrawingAPI2 ( DrawingAPI ): def drawCircle ( self , x , y , radius ): tipăriți „API2.circle la %f : %f radius %f % ( x , y , radius ) # Clasa de abstracție Formă : # Remiză def la nivel scăzut ( self ): trece # Definiție de nivel înalt resizeByPercentage ( self , pct ): trece # Clasa de abstracție rafinată CircleShape ( Shape ): def __init__ ( self , x , y , radius , drawingAPI ): self . __x = x sine . __y = y self . __radius = raza sine . __drawingAPI = drawingAPI # low-level ie specifică implementării def draw ( self ): self . __drawingAPI . drawCircle ( self . __x , self . __y , self . __radius ) # de nivel înalt, adică def . specifică abstracției resizeByPercentage ( self , pct ): self . __raza *= pct def main (): forme = [ CircleShape ( 1 , 2 , 3 , DrawingAPI1 ()), CircleShape ( 5 , 7 , 11 , DrawingAPI2 ()) ] pentru forma in forme : forma . resizeByPercentage ( 2.5 ) forma . trage () if __name__ == "__main__" : principal ()

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 )

Link -uri