Diferenças entre edições de "Adapter"

13 491 bytes removidos ,  01h30min de 18 de novembro de 2011
Reversão. Conteúdo copiado de [www.i2p.com.br/ricardo/ppadapter.pdf]
(Reversão. Conteúdo copiado de [www.i2p.com.br/ricardo/ppadapter.pdf])
'''Adapter''', também conhecido como Wrapper, é um [[padrões de projeto de software|padrão de projeto de software]] (do [[língua inglesa|inglês]] ''design pattern''). Este padrão é utilizado para 'adaptar' a [[Interface (ciência da computação)|interface]] de uma [[Classe (programação) |classe]]. O Adapter permite que classes com interfaces incompatíveis possam interagir.
'''Adapter''', O Adapter (tambem conhecido como Wrapper), é classificado como um [[padrão estrutural]], faz com que uma interface adaptada seja compatível com outra, fornecendo uma abstração de diferentes interfaces. O Adapter faz com que classes com interfaces incompatíveis trabalhem em conjunto.<ref>{{referência a livro|Autor=LASATERS,Christopher|Título=Design Patterns|Subtítulo=wordware Applications Library|Editora=Jones & Bartlett Learning|Local de publicação=Massachusetts|Ano=2006|Edição=1|ID={{ISBN|1598220314}}}} página 206</ref>
 
 
'''Adapter''' permite que um objeto cliente utilize serviços de outros objetos com interfaces diferentes por meio de uma interface única.
 
[[Imagem:Adapter.PNG]]
'''Padrão de projeto de software Adapter.'''<ref>{{referência a livro|Autor=GAMMA, Erich|Título=PADRÕES DE PROJETO|Subtítulo=Soluções Reutilizaveis de Software Orientado a Objetos|Editora=Bookman|Local de publicação=Boston|Ano=2000|Edição=1|ID={{ISBN|0201633612}}}} página 70</ref>
 
O padrão abrange tanto o escopo de classe como tambem de objetos, sendo que o primeiro utiliza herança multipla e é utilizado quando o alvo é uma interface, já o de objetos utiliza agregação pois o alvo que necessita ser adaptado é uma classe.
 
O Adapter possui 3 elementos importantes, o Alvo, [[classe]] ou [[interface]] que desejamos implementar o Adapter, outro elemento é o próprio Adapter, possibilita a junção de duas classes diferentes, e por último o Adaptado, classe que contém os métodos e funcionalidades acessados pelo Alvo.
 
Um exemplo usual do conceito de Adapter é o uso de tomadas em países diferentes, cada pais adota um padrão, para resolver esse problema usa-se um adaptador que convertem um tipo de adaptador em outro. Em programação funciona da mesma forma, o Adapter funciona como um elo de ligação de duas classes diferentes. Um outro exemplo de sua utilização pode ser visto na API da linguagem [[Java]] para tratamento de eventos (MouseAdapter, WindowAdapter).
 
As tomadas têm uma interface, que dizem se ela é uma tomada de dois ou de três pinos.
Essa interface deve possuir um método que diz o que a tomada faz: fornecer energia
elétrica. Os plugues também deverão ter interfaces que dirão se eles são plugues de dois ou três
pinos e possuirão um método para conectá- lo a uma tomada. Um plugue de 3 pinos só pode se conectar a uma tomada de 3 pinos e um plugue de 2 pinos a uma tomada de 2 pinos.
 
Precisamos encaixar um plugue de três pinos em uma tomada de dois pinos, portanto
deveremos usar um adaptador.
 
*Sem um adaptador uma interface não converte para outra, portanto um adaptador irá se comportar como uma tomada de 3 pinos.
 
*Cria-se um adaptador com uma referencia para o objeto adaptado.
 
*Implementa-se a interface TomadaTresPinos como uma forma de traduzir o comportamento da interface adaptada.
 
 
'''Quando usar Adapter ?'''
 
*Quando precisar inserir uma nova classe em um projeto e as interfaces forem diferentes.
*Se quiser criar classes reutilizáveis que cooperem com futuras classes imprevistas.
*Quando precisar utilizar varias subclasses, sendo impraticável implementar uma interface para cada uma.
 
 
 
'''Adaptador de Objetos'''<ref>{{referência a livro|Autor=HORSTMANN, Cay David|Título=PADRÕES E PROJETO DE SOFTWARE ORIENTADOS A OBJETOS|Subtítulo=|Editora= Bookman|Local de publicação= Nova Jersey|Ano=2007|Edição=2|ID={{ISBN|9788560031511}}}} páginas 385 e 386</ref>.
 
*O cliente só vê a interface ClasseAbstrata, só o Adapter sabe da existência do [[cliente]] e da classe adaptada.
*A classe Adaptador que implementa a Classe Abstrata.
*O Adaptador se comunica com a Classe Desejada.
*Todas as solicitações são feitas a Classe Desejada.
 
Como o Adapter vincula o Cliente a um interface, pode-se usar vários adaptadores cada um deles com diferentes classes e subclasses.
A desvantagem dos Adaptadores de Objeto é em relação a implementação, é preciso escrever todo o código necessário para as chamadas da classe adaptada.
 
'''Adaptador de Classes'''
 
Requer a utilização de herança múltipla.
 
O Adapter funciona como um interpretador, a classe Cliente utiliza a classe Alvo, todos os métodos chamados pelo cliente pertence a esse classe, a classe Adaptado não possui os métodos da classe Alvo, o trabalho do Adaptador é traduzir as chamadas dos métodos da classe Alvo em chamada aos métodos da classe Adaptado.A implementação de Adaptadores de Classes é muito mais simples do que Adaptadores de Objetos, pois normalmente envolve menos código.
 
 
=='''Aplicabilidade'''==
 
Use o padrão quando:
 
*Precisar utilizar uma classe existente, entretanto sua interface não corresponde a interface que utiliza.
*Criar uma classe reutilizável que coopere com classes não-reutilizáveis ou previstas.
 
*Classes com interfaces incompatíveis.
*Precisar utilizar varias subclasses.
 
=='''Padrões Relacionados'''==
 
O Padrão [[Bridge]] – tem uma estrutura semelhante, porem tem por definição separar uma interface de sua aplicação, um adaptador se destina a mudar a interface de uma classe/objeto já existente.
 
O Padrão [[Façade]] – Em ambos os padrões, Façade e Adapter, existe um classe (ou classes) que precisam de uma interface necessária, entretanto, o Facade simplifica uma interface, ao passo que o Adapter converte para uma já existente adaptando-a ao projeto.<ref>{{referência a livro|Autor=FREEMAN, Eric|Título=Use a Cabeça!PADRÕES DE PROJETO|Subtítulo=DESIGN PATTERNS|Editora= Alta Books|Local de publicação= Rio de Janeiro|Ano=2007|Edição=2|ID={{ISBN|9788576081746}}}}</ref>
 
==Implementações==
=== [[Pseudocódigo]] ===
=== [[C#]] ===
<pre>using System;
 
class MainApp
{
static void Main()
{
// Create adapter and place a request
Target target = new Adapter();
target.Request();
 
// Wait for user
Console.Read();
}
}
 
// "Target"
class Target
{
public virtual void Request()
{
Console.WriteLine("Called Target Request()");
}
}
 
// "Adapter"
class Adapter : Target
{
private Adaptee adaptee = new Adaptee();
 
public override void Request()
{
// Possibly do some other work
// and then call SpecificRequest
adaptee.SpecificRequest();
}
}
 
// "Adaptee"
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Called SpecificRequest()");
}
}</pre>
 
=== [[C++]] ===
<pre>#include <iostream.h>
 
typedef int Coordinate;
typedef int Dimension;
 
// Desired interface
class Rectangle
{
public:
virtual void draw() = 0;
};
 
// Legacy component
class LegacyRectangle
{
public:
LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2)
{
x1_ = x1;
y1_ = y1;
x2_ = x2;
y2_ = y2;
cout << "LegacyRectangle: create. (" << x1_ << "," << y1_ << ") => ("
<< x2_ << "," << y2_ << ")" << endl;
}
void oldDraw()
{
cout << "LegacyRectangle: oldDraw. (" << x1_ << "," << y1_ <<
") => (" << x2_ << "," << y2_ << ")" << endl;
}
private:
Coordinate x1_;
Coordinate y1_;
Coordinate x2_;
Coordinate y2_;
};
 
// Adapter wrapper
class RectangleAdapter: public Rectangle, private LegacyRectangle
{
public:
RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h):
LegacyRectangle(x, y, x + w, y + h)
{
cout << "RectangleAdapter: create. (" << x << "," << y <&lt;
"), width = " &lt;&lt; w &lt;&lt; ", height = " &lt;&lt; h &lt;&lt; endl;
}
virtual void draw()
{
cout &lt;&lt; "RectangleAdapter: draw." &lt;&lt; endl;
oldDraw();
}
};
 
int main()
{
Rectangle *r = new RectangleAdapter(120, 200, 60, 40);
r->draw();
}</pre>
 
=== [[Delphi]] ===
<pre>unit Adapter;
 
interface
 
uses SysUtils, Classes;
 
type
 
//The new class
 
TNewCustomer = class
private
FCustomerID: Longint;
FFirstName: string;
FLastName: string;
FDOB: TDateTime;
protected
function GetCustomerID: Longint; virtual;
function GetFirstName: string; virtual;
function GetLastName: string; virtual;
function GetDOB: TDateTime; virtual;
public
constructor Create(CustID: Longint); virtual;
property CustomerID: Longint read GetCustomerID;
property FirstName: string read GetFirstName;
property LastName: string read GetLastName;
property DOB: TDateTime read GetDOB;
end;
 
//An interface method
 
//Lets us hide details of TOldCustomer from the client
 
function GetCustomer(CustomerID: Longint): TNewCustomer;
 
implementation
 
const
Last_OldCustomer_At_Year_2000 = 15722;
Last_OldCustomer_In_Database = 30000;
 
//The new class
 
constructor TNewCustomer.Create(CustID: Longint);
begin
FCustomerID := CustID;
FFirstName := 'A';
FLastName := 'New_Customer';
FDOB := Now;
end;
 
function TNewCustomer.GetCustomerID: Longint;
begin
Result := FCustomerID;
end;
function TNewCustomer.GetFirstName: string;
begin
Result := FFirstName;
end;
 
function TNewCustomer.GetLastName: string;
begin
Result := FLastName;
end;
 
function TNewCustomer.GetDOB: TDateTime;
begin
Result := FDOB;
end;
 
type
 
//The old class
TOldDOB = record
Day: 0..31;
Month: 1..12;
Year: 0..99;
end;
 
 
TOldCustomer = class
FCustomerID: Integer;
FName: string;
FDOB: TOldDOB;
public
constructor Create(CustID: Integer);
property CustomerID: Integer read FCustomerID;
property Name: string read FName;
property DOB: TOldDOB read FDOB;
end;
constructor TOldCustomer.Create(CustID: Integer);
begin
FCustomerID := CustomerID;
FName := 'An Old_Customer';
with FDOB do begin
Day := 1;
Month := 1;
Year := 1;
end;
end;
type
 
//The Adapter class
 
TAdaptedCustomer = class(TNewCustomer)
private
FOldCustomer: TOldCustomer;
protected
function GetCustomerID: Longint; override;
function GetFirstName: string; override;
function GetLastName: string; override;
function GetDOB: TDateTime; override;
public
constructor Create(CustID: Longint); override;
destructor Destroy; override;
end;
 
 
//The Adapter class
 
constructor TAdaptedCustomer.Create(CustID: Longint);
begin
inherited Create(CustID);
FOldCustomer := TOldCustomer.Create(CustID);
end;
 
destructor TAdaptedCustomer.Destroy;
begin
FOldCustomer.Free;
inherited Destroy;
end;
 
function TAdaptedCustomer.GetCustomerID: Longint;
begin
Result := FOldCustomer.CustomerID;
end;
 
function TAdaptedCustomer.GetFirstName: string;
var
SpacePos: integer;
begin
SpacePos := Pos(' ', FOldCustomer.Name);
if SpacePos = 0 then
Result := ''
else
Result := Copy(FOldCustomer.Name,1,SpacePos-1);
end;
 
function TAdaptedCustomer.GetLastName: string;
var
SpacePos: integer;
begin
SpacePos := Pos(' ', FOldCustomer.Name);
if SpacePos = 0 then
Result := FOldCustomer.Name
else
Result := Copy(FOldCustomer.Name,SpacePos+1,255);
end;
 
function TAdaptedCustomer.GetDOB: TDateTime;
var
FullYear: Word;
begin
if CustomerID > Last_OldCustomer_At_Year_2000 then
FullYear := 2000 + FOldCustomer.DOB.Year
else
FullYear := 1900 + FOldCustomer.DOB.Year;
Result := EncodeDate(FullYear, FOldCustomer.DOB.Month, FOldCustomer.DOB.Day);
end;
 
function GetCustomer(CustomerID: Longint): TNewCustomer;
begin
if CustomerID > Last_OldCustomer_In_Database then
Result := TNewCustomer.Create(CustomerID)
else
Result := TAdaptedCustomer.Create(CustomerID) as TNewCustomer;
end;
 
end.</pre>
 
=== [[Java]] ===
<pre>class SquarePeg {
private double width;
public SquarePeg( double w ) { width = w; }
public double getWidth() { return width; }
public void setWidth( double w ) { width = w; }
}
 
/* The NEW */
class RoundHole {
private int radius;
public RoundHole( int r ) {
radius = r;
System.out.println( "RoundHole: max SquarePeg is " + r * Math.sqrt(2) );
}
public int getRadius() { return radius; }
}
 
// Design a "wrapper" class that can "impedance match" the old to the new
class SquarePegAdapter {
 
// The adapter/wrapper class "has a" instance of the legacy class
private SquarePeg sp;
 
public SquarePegAdapter( double w ) { sp = new SquarePeg( w ); }
 
// Identify the desired interface
public void makeFit( RoundHole rh ) {
// The adapter/wrapper class delegates to the legacy object
double amount = sp.getWidth() - rh.getRadius() * Math.sqrt(2);
System.out.println( "reducing SquarePeg " + sp.getWidth() + " by " + ((amount < 0) ? 0 : amount) + " amount" );
if (amount > 0) {
sp.setWidth( sp.getWidth() - amount );
System.out.println( " width is now " + sp.getWidth() );
}
}
}
 
class AdapterDemoSquarePeg {
public static void main( String[] args ) {
RoundHole rh = new RoundHole( 5 );
SquarePegAdapter spa;
 
for (int i=6; i < 10; i++) {
spa = new SquarePegAdapter( (double) i );
// The client uses (is coupled to) the new interface
spa.makeFit( rh );
}
}
}</pre>
 
=== [[PHP]] ===
<pre><?php
 
class SimpleBook {
private $author;
private $title;
function __construct($author_in, $title_in) {
$this->author = $author_in;
$this->title = $title_in;
}
function getAuthor() {
return $this->author;
}
function getTitle() {
return $this->title;
}
}
 
class BookAdapter {
private $book;
function __construct(SimpleBook $book_in) {
$this->book = $book_in;
}
function getAuthorAndTitle() {
return $this->book->getTitle().' by '.$this->book->getAuthor();
}
}
 
// client
 
writeln('BEGIN TESTING ADAPTER PATTERN');
writeln('');
 
$book = new SimpleBook("Gamma, Helm, Johnson, and Vlissides", "Design Patterns");
$bookAdapter = new BookAdapter($book);
writeln('Author and Title: '.$bookAdapter->getAuthorAndTitle());
writeln('');
 
writeln('END TESTING ADAPTER PATTERN');
 
function writeln($line_in) {
echo $line_in."<br/>";
}
 
?></pre>
 
{{Referências}}
{{esboço-informática}}
 
22 741

edições