Adapter pattern: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
mNessun oggetto della modifica |
m Bot: fix wl, replaced: Design Patterns patterns → Design pattern |
||
(69 versioni intermedie di 49 utenti non mostrate) | |||
Riga 1:
{{F|programmazione|febbraio 2013}}
Con il nome '''adapter''', o '''adattatore''' si denota un ''[[design pattern]]'' utilizzato in [[informatica]] nella [[programmazione orientata agli oggetti]]. A volte viene chiamato ''wrapper'' (ovvero ''involucro'') per il [[#Struttura|suo schema di funzionamento]].
Il fine dell'''adapter'' è di fornire una soluzione astratta al problema dell'interoperabilità tra interfacce differenti. Il problema si presenta ogni qual volta nel progetto di un ''[[software]]'' si debbano utilizzare sistemi di supporto (come per esempio [[Libreria (software)|librerie]]) la cui interfaccia non è perfettamente compatibile con quanto richiesto da applicazioni già esistenti. Invece di dover riscrivere parte del sistema, compito oneroso e non sempre possibile se non si ha a disposizione il [[codice sorgente]], può essere comodo scrivere un ''adapter'' che faccia da tramite.
L'''Adapter'' è un ''pattern'' strutturale che può essere basato sia su [[Classe (informatica)|classi]] che su [[Oggetto (informatica)|oggetti]].
Questo ''design pattern'' è parte fondamentale della programmazione a oggetti ed è stato formalizzato per la prima volta da [[Erich Gamma]], [[Richard Helm]], [[Ralph Johnson (informatico)|Ralph Johnson]] e [[John Vlissides]] - la cosiddetta ''[[Gang of Four (scrittori)|Gang of Four]]'' - nel libro ''[[Design Patterns]]''.
==Applicabilità==
L'uso del pattern ''Adapter'' risulta utile quando interfacce di classi differenti devono comunque poter comunicare tra loro. Alcuni casi possono includere
*l'utilizzo di una classe esistente che presenti un'interfaccia diversa da quella desiderata;
*la scrittura di una determinata classe senza poter conoscere a priori le altre classi con cui dovrà operare, in particolare senza poter conoscere quale specifica interfaccia sia necessario che la classe debba presentare alle altre.
Un altro contesto è quello in cui si desidera che l'invocazione di un [[metodo (informatica)|metodo]] di un oggetto da parte dei ''[[client]]'' avvenga solo in maniera indiretta: il metodo "target" viene incapsulato all'interno dell'oggetto, mentre uno o più metodi "pubblici" fanno da tramite con l'esterno. Questo consente alla classe di subire modifiche future mantenendo la retrocompatibilità, oppure di implementare in un unico punto una funzionalità alla quale i ''client'' accedono tramite metodi più "comodi" da usare e con ''signatures'' differenti.
==Struttura==
{{S sezione|informatica}}
Il pattern ''Adapter'' può essere basato su classi, utilizzando l'[[ereditarietà (informatica)|ereditarietà]] multipla per adattare interfacce diverse con il meccanismo dell'ereditarietà, oppure su oggetti con la composition, ovvero includendo l’oggetto sorgente nell’implementazione dell’adapter..
<!--
===Basata su classi===
La classe ADAPTEE rappresenta l'oggetto la cui interfaccia deve esse adattata.
Ipotizziamio una classe ADAPTEE di nome AUTO che abbia un metodo pubblico chiamato getNumeroTarga (richiamabile quindi come AUTO.getNumeroTarga).
Obiettivo :
Vogliamo creare una nuova classe ADAPTER che adatti tale interfaccia creando un nuovo metodo più semplice da usare e dal nome getTarga.
Soluzione :
Creiamo un'interfaccia TARGET che contenga al suo interno i prototipi dei due metodi getNumeroTarga e getTarga.
Creiamo una classe ADAPTER dal nome AUTOMOBILE che eredita (o estende) AUTO ed al tempo stesso implementa l'intefaccia TARGET. Facendo così, in AUTOMOBILE avremo sia getNumeroTarga che getTarga.
Implementiamo il nuovo metodo getTarga richiamando semplicemente il vecchio metodo getNumeroTarga, già implementato in AUTO.
Ci sarà, infine, la classe CLIENT che utilizzerà l'interfaccia modificata istanziando una classe di tipo AUTOMOBILE. Tale istanza potrà indifferentemente utilizzare il metodo getNumeroTarga o il metodo getTarga.
===Basata su oggetti===
La variante basata su oggetti si differenzia da quella basata su classi in quanto la classe ADAPTER (cioè quella che adatta la vecchia interfaccia) non eredità (o estende) la classe ADAPTEE ma si limita ad implementare l'interfaccia TARGET.
Nel corpo dell'ADAPTER sarà presente un'istanza privata della classe ADAPTEE in modo da poter implementare il metodo getTarga semplicemente richiamando il metodo getNumeroTarga di tale istanza.
-->
==Partecipanti==
[[File:Adapter using delegation UML class diagram.svg|thumb|upright=1.6|Diagramma UML del Pattern]]
* '''Adaptee''': definisce l'interfaccia che ha bisogno di essere adattata.
Riga 10 ⟶ 43:
* '''Adapter''': adatta l'interfaccia Adaptee all'interfaccia Target.
==
===PHP===
<syntaxhighlight lang="php">
// Esempio Adapter Pattern
interface IFormatPresaTedesca
{
public function inserisciSpinaTedesca();
public function inviaCorrente();
}
interface IFormatPresaItaliana
{
public function inserisciSpinaItaliana();
public function inviaCorrente();
}
// Adaptee
class LavatriceTedesca implements IFormatPresaTedesca
{
private $spinaInserita = FALSE;
private $correntePresente = FALSE;
public function inserisciSpinaTedesca()
{
$this->spinaInserita = TRUE;
echo "Spina Tedesca inserita\n";
}
public function inviaCorrente()
{
if($this->spinaInserita)
{
$this->correntePresente = TRUE;
echo "Corrente lavatrice Tedesca presente\n";
}
else
{
echo "Corrente lavatrice Tedesca non presente\n";
}
}
public function lava()
{
if($this->correntePresente)
{
echo "Lavaggio iniziato\n";
echo "Lavaggio 25%\n";
echo "Lavaggio 50%\n";
echo "Lavaggio 75%\n";
echo "Lavaggio terminato\n";
}
else
{
echo "Controllare presa\n";
}
}
}
// Adapter
class AdattatorePresaTedesca implements IFormatPresaItaliana
{
private $presa;
public function __construct(IFormatPresaTedesca $presa)
{
$this->presa = $presa;
}
public function inserisciSpinaItaliana()
{
echo "Adattatore presa Tedesca inserito\n";
$this->presa->inserisciSpinaTedesca();
}
public function inviaCorrente()
{
$this->presa->inviaCorrente();
}
public function lava()
{
$this->presa->lava();
}
}
class LavatriceItaliana implements IFormatPresaItaliana
{
private $correntePresente = FALSE;
private $spinaInserita = FALSE;
public function inserisciSpinaItaliana()
{
$this->spinaInserita = TRUE;
echo "Spina Italiana inserita\n";
}
public function inviaCorrente()
{
if($this->spinaInserita)
{
$this->correntePresente = TRUE;
echo "Corrente lavatrice Italiana presente\n";
}
else
{
echo "Corrente lavatrice Italiana non presente\n";
}
}
public function lava()
{
if($this->correntePresente)
{
echo "Lavaggio iniziato\n";
echo "Lavaggio 25%\n";
echo "Lavaggio 50%\n";
echo "Lavaggio 75%\n";
echo "Lavaggio terminato\n";
}
else
{
echo "Controllare presa\n";
}
}
}
// Client
class EseguiLavaggio
{
private $lavatrice;
private $lavatriceConAdattatore;
public function __construct()
{
echo "---Lavaggio con Lavatrice Tedesca iniziato---\n";
$this->lavatrice = new LavatriceTedesca();
$this->lavatriceConAdattatore = new AdattatorePresaTedesca($this->lavatrice);
$this->lavatriceConAdattatore->inserisciSpinaItaliana();
$this->lavatriceConAdattatore->inviaCorrente();
$this->lavatriceConAdattatore->lava();
echo "---Vestiti pronti---\n\n";
}
}
$lavaggio = new EseguiLavaggio();
//Risultato: #quanton81
//---Lavaggio con Lavatrice Tedesca iniziato---
//Adattatore presa Tedesca inserito
//Spina Tedesca inserita
//Corrente lavatrice Tedesca presente
//Lavaggio iniziato
//Lavaggio 25%
//Lavaggio 50%
//Lavaggio 75%
//Lavaggio terminato
//---Vestiti pronti---
</syntaxhighlight>
== Voci correlate ==
* [[Design pattern]]
* [[Bridge pattern]]
* [[Decorator]]
* [[Proxy pattern]]
== Altri progetti ==
{{interprogetto}}
{{Design pattern}}
[[Categoria:
|