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