Adapter: diferenças entre revisões

Origem: Wikipédia, a enciclopédia livre.
Conteúdo apagado Conteúdo adicionado
Linha 67: Linha 67:
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 [[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 [[Facade]] – 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>
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==
==Implementações==

Revisão das 13h38min de 16 de novembro de 2011

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.[1]


Padrão de projeto de software Adapter.[2]

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[3].

  • 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.[4]

Implementações

Pseudocódigo

C#

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()");
    }
  }

C++

#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 << 
          "), width = " << w << ", height = " << h << endl;
    }
    virtual void draw()
    {
        cout << "RectangleAdapter: draw." << endl;
        oldDraw();
    }
};

int main()
{
  Rectangle *r = new RectangleAdapter(120, 200, 60, 40);
  r->draw();
}

Delphi

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.

Java

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 );
      }
   }
}

PHP

<?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/>";
  }

?>

Referências

  1. LASATERS,Christopher (2006). Design Patterns. wordware Applications Library 1 ed. [S.l.]: Jones & Bartlett Learning. ISBN 1598220314  Parâmetro desconhecido |Autor= ignorado (|autor=) sugerido (ajuda) página 206
  2. GAMMA, Erich (2000). PADRÕES DE PROJETO. Soluções Reutilizaveis de Software Orientado a Objetos 1 ed. [S.l.]: Bookman. ISBN 0201633612  Parâmetro desconhecido |Autor= ignorado (|autor=) sugerido (ajuda) página 70
  3. HORSTMANN, Cay David (2007). PADRÕES E PROJETO DE SOFTWARE ORIENTADOS A OBJETOS 2 ed. [S.l.]: Bookman. ISBN 9788560031511  Parâmetro desconhecido |Autor= ignorado (|autor=) sugerido (ajuda); páginas 385 e 386
  4. FREEMAN, Eric (2007). Use a Cabeça!PADRÕES DE PROJETO. DESIGN PATTERNS 2 ed. [S.l.]: Alta Books. ISBN 9788576081746  Parâmetro desconhecido |Autor= ignorado (|autor=) sugerido (ajuda)
Ícone de esboço Este artigo sobre informática é um esboço. Você pode ajudar a Wikipédia expandindo-o.