2009-08-19 17 views
21

Estoy tratando de entender el patrón de adaptador y su uso en el mundo real. Después de revisar varios artículos en internet y www.dofactory.com, creé este código de muestra. Solo quiero saber si mi entendimiento es correcto. En el siguiente ejemplo, he creado un objeto MSDAO en la clase Adapter. Más tarde lo cambié a OracleDAO.Descripción del patrón de adaptador

class Client 
{ 
    static void Main(string[] args) 
    { 
    ITarget objAdapter = new Adapter(); 
    object dummyObject = objAdapter.GetData(); 
    } 
} 

Interface ITarget 
{ 
    public void GetData(); 
} 

//Decision to use MSDAO 

class Adapter : ITarget 
{ 
    public void GetData() 
    { 
    MSDAO objmsdao = new MSDAO(); 
    objmsdao.GetData(); 
    } 
} 

//After a month, the decision to use OracaleDAO was taken, so the code change 

class Adapter : ITarget 
{ 
    public void GetData() 
    { 
    OracleDAO objoracledao = new OracleDAO(); 
    objoracledao.GetData(); 
    } 
} 

Respuesta

61

En general, el adapter transforma una interfaz a otra, sino que simplemente puede envolver el comportamiento de aislar su clase a partir de la implementación subyacente. En su caso, está utilizando un adaptador, pero podría haber definido tan fácilmente los objetos DAO para simplemente implementar la interfaz y programar contra la interfaz. El patrón del adaptador generalmente se usa cuando no tiene control sobre la clase objetivo. Mi uso principal del patrón de adaptador sería crear contenedores para una clase de marco que no implementa una interfaz.

Digamos que quiero simular una clase de marco que no implementa una interfaz (y no tiene métodos virtuales). Con muchas apologías burlonas esto es difícil o imposible de hacer. Lo que haré, entonces, es definir mi propia interfaz como un subconjunto de la firma de la clase a la que me dirijo. Implemento una clase de contenedor que implementa esta interfaz y simplemente delega las llamadas a la clase de marco envuelto. Esta clase de contenedor funciona como un adaptador para la clase de marco. Mis clases usan este adaptador en lugar de la clase framework, pero obtienen el comportamiento de la clase framework.

public interface IFoo 
{ 
    void Bar(); 
} 

public class FooWrapper : IFoo 
{ 
     private FrameworkFoo Foo { get; set; } 

     public FooWrapper(FrameworkFoo foo) 
     { 
      this.Foo = foo; 
     } 

     public void Bar() 
     { 
      this.Foo.Bar(); 
     } 
} 

Ten en cuenta también el caso de que usted tiene un par de diferentes clases que tienen básicamente la misma funcionalidad, pero diferentes firmas y que desea ser capaz de utilizar de forma indistinta. Si no puede transformarlos (o no quiere hacerlo por otros motivos), puede escribir una clase de adaptador que defina una interfaz común y traduzca entre los métodos de dicha interfaz y los métodos disponibles en las clases de destino.

clases marco:

public class TargetA 
{ 
    public void Start() { ... } 
    public void End() { ... } 
} 

public class TargetB 
{ 
    public void Begin() { ... } 
    public void Terminate() { ... } 
} 

un adaptador para ellos

public interface ITargetAdapter 
{ 
    void Open(); 
    void Close(); 
} 

public class AdapterA : ITargetAdapter 
{ 
    private TargetA A { get; set; } 

    public AdapterA(TargetA a) 
    { 
      this.A = a; 
    } 

    public void Open() { this.A.Start(); } 
    public void Close() { this.A.End(); } 
} 

public class AdapterB : ITargetAdapter 
{ 
    private TargetB B { get; set; } 

    public AdapterB(TargetB a) 
    { 
      this.B = a; 
    } 

    public void Open() { this.B.Begin(); } 
    public void Close() { this.B.Terminate(); } 
} 

Entonces utilizado como:

ITargetAdapter adapter = new AdapterA(new TargetA()); 
adapter.Open(); 
adapter.Close();  
+0

En su ejemplo, ha completado su clase de infraestructura con una clase que implementa una interfaz. Lo he entendido, pero ¿puedes aclarar cómo has "transformado una interfaz en otra? Gracias. – pradeeptp

+0

En este caso, la interfaz técnicamente no existía antes. Es una especie de caso degenerado en el sentido de que en realidad estás creando un interfaz para una clase que no tenía uno. El segundo ejemplo (recién agregado) lo demuestra mejor. – tvanfosson

+0

Gracias. Esto está muy claro ahora! – pradeeptp

2

Un ejemplo canónico interior existe el marco .NET en la clase System.Drawing.Bitmap.

Este mapa de bits tiene un constructor que permite cargar una imagen desde un Stream:

public Bitmap(
    Stream stream 
) 

lo que no saben, es que internamente la clase de .NET Bitmap es una envoltura alrededor de la clase GDI + Bitmap, y su constructor que toma un IStream:

Bitmap(
    [in] IStream *stream, 
    [in] BOOL useIcm 
); 

Así que en el mundo C#, cuando llamo:

new Bitmap(stream); 

que tiene que dar la vuelta y llamar:

IStream stm; 
IntPtr gpBitmap; 
GdipCreateBitmapFromStream(stm, out gpBitmap); 

La pregunta es cómo presentar una.NET Corriente objetar a un método que espera una interfaz COM IStream.

De ahí el interior de clase GPStream:

internal class GPStream : IStream 
{ 
    GPStream(Stream stream) { ... } 
} 

Es necesario presentar una interfaz IStream a su Stream objeto:

IStream          Stream 
=======================================  ===================================== 
int Read(IntPtr buf, int len);   --> int Read(byte[] buffer, int offset, int count) 
int Write(IntPtr buf, int len);   --> void Write(byte[] buffer, int offset, int count); 
long Seek(long dlibMove, int dwOrigin); --> long Seek(long offset, SeekOrigin orgin) 
...           ... 

Así que ahora tiene un adaptador:

enter image description here

y el código es algo como:

IStream stm = new GPStream(stream); //adapter to convert Stream --> IStream 
IntPtr gpBitmap; 

GdipCreateBitmapFromStream(stm, out gpBitmap); 
0

He añadido los comentarios que se espera le ayudará a conseguir su oído en todo el conjunto adaptador/adaptée/cliente/jerga Itarget - que es un poco confuso - con un ejemplo que Espero que sea más intuitivo, con suerte :) (dedos cruzados).

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     // Brian and freddie know only how to say Greetings. But when they tour 
     // internationally, they will need a translator so when they say Greetings() 
     // the appropriate non-English response comes out of their mouth. 
     // they need to make use of the adapter pattern: 

     // When in Japan: 
     ITarget translator = new JapaneseTranslator(new JapaneseSpeaker()); 
     EnglishMan freddieMercury = new EnglishMan(translator); 

     // Freddie greets the Tokyo crowd, though he doesn't know a word of Japanese 
     Console.WriteLine(freddieMercury.Greetings()); // "Konichiwa, hisashiburi!" 

     // when in France: 
     ITarget translator2 = new FrenchTranslator(new FrenchSpeaker()); 
     EnglishMan brianMay = new EnglishMan(translator2); 

     // Brian greets the crowd in Paris, though he doesn't know a word in French 
     Console.WriteLine(brianMay.Greetings()); // "Bonjour!" 

     // alternatively, the translators can also do the greeting: 
     Console.WriteLine(translator.Greetings()); // "Konichiwa, hisashiburi!" 
     Console.WriteLine(translator2.Greetings()); // "Bonjour!" 
    } 

    /// <summary> 
    /// This is the client. 
    /// </summary> 
    public class EnglishMan : ITarget 
    { 
     private ITarget target; 

     public EnglishMan(ITarget target) 
     { 
      this.target = target; 
     } 

     public string Greetings() 
     { 
      return target.Greetings(); 
     } 
    } 

    /// <summary> 
    /// The target interface 
    /// </summary> 
    public interface ITarget 
    { 
     string Greetings(); 
    } 

    /// <summary> 
    /// This is the adaptor 
    /// </summary> 
    public class JapaneseTranslator : ITarget 
    { 
     private JapaneseSpeaker japanese; 

     public JapaneseTranslator(JapaneseSpeaker japanese) 
     { 
      this.japanese = japanese; 
     } 

     public string Greetings() 
     { 
      return japanese.Konnichiwa(); 
     } 
    } 

    /// <summary> 
    /// This is the adaptee 
    /// </summary> 
    public class JapaneseSpeaker 
    { 
     public JapaneseSpeaker() 
     { 
     } 

     public string Konnichiwa() 
     { 
      return "Konichiwa, hisashiburi!"; 
     } 
    } 

    /// <summary> 
    /// This is the adaptor 
    /// </summary> 
    public class FrenchTranslator : ITarget 
    { 
     private FrenchSpeaker french; 

     public FrenchTranslator(FrenchSpeaker french) 
     { 
      this.french = french; 
     } 

     public string Greetings() 
     { 
      return french.Bonjour(); 
     } 
    } 

    /// <summary> 
    /// This is the adaptee 
    /// </summary> 
    public class FrenchSpeaker 
    { 
     public string Bonjour() 
     { 
      return "Bonjour!!"; 
     } 
    } 
} 
Cuestiones relacionadas