Question

Je suis en train de comprendre modèle d'adaptation et son utilisation dans le monde réel. Après avoir traversé plusieurs articles sur internet et www.dofactory.com, j'ai créé cet exemple de code. Je veux juste savoir si je comprends bien. Dans l'exemple ci-dessous, je l'ai créé objet MSDAO dans la classe d'adaptateur. Plus tard, je l'ai changé OracleDAO.

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();
  }
}
Était-ce utile?

La solution

En général, le modèle d'adaptateur transforme une interface dans une autre, mais il peut tout simplement envelopper le comportement d'isoler votre classe de la mise en œuvre sous-jacente. Dans votre cas, vous utilisez un adaptateur, mais vous pouvez tout aussi facilement avoir défini les objets DAO pour mettre en œuvre simplement l'interface et programmée sur l'interface. Le modèle d'adaptateur est généralement utilisé lorsque vous ne disposez pas de contrôle sur la classe cible. Mon utilisation principale du modèle d'adaptation serait de créer des emballages pour une classe de cadre qui ne met pas en œuvre une interface.

dis que je veux moquer une classe-cadre qui ne met pas en œuvre une interface (et ne dispose pas des méthodes virtuelles). Avec beaucoup apis moqueurs cela est difficile, voire impossible, de le faire. Ce que je vais faire, alors, est de définir ma propre interface comme un sous-ensemble de la signature de la classe je cible. Je mets en œuvre une classe wrapper qui implémente cette interface et simplement les délégués des appels à la classe cadre enveloppé. Cette classe d'emballage fonctionne comme un adaptateur pour la classe-cadre. Mes classes utilisent cet adaptateur au lieu de la classe-cadre, mais obtenir la classe cadre comportement.

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

Prenons aussi le cas où vous avez deux ou trois différentes classes qui ont essentiellement les mêmes fonctionnalités, mais différentes signatures et vous voulez être en mesure de les utiliser de manière interchangeable. Si vous ne pouvez pas transformer ces (ou ne veulent pas pour d'autres raisons), vous pouvez écrire une classe d'adaptateur qui définit une interface commune et se traduit entre les méthodes et les méthodes disponibles sur les classes cibles de cette interface.

classes Cadre:

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

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

Un adaptateur pour les

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

Ensuite, utilisé comme:

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

Autres conseils

Un exemple canonique dans le framework .NET existe dans le System.Drawing.Bitmap classe .

Ce Bitmap a un constructeur qui vous permet de charger une image à partir d'un Stream :

public Bitmap(
    Stream stream
)

ce que vous ne savez pas, est que l'intérieur de la classe Bitmap .NET est une enveloppe autour du GDI + la classe de Bitmap, et son constructeur qui prend un IStream :

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

dans le monde C #, quand je l'appelle:

new Bitmap(stream);

il doit tourner autour et appeler:

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

La question est de savoir comment présenter un .NET Flux objet à une méthode qui attend un COM IStream interface.

D'où la classe GPStream interne:

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

Vous devez présenter une interface IStream à votre objet Stream:

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

Alors maintenant, vous avez un adaptateur:

Et le code est quelque chose comme:

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

GdipCreateBitmapFromStream(stm, out gpBitmap);

J'ai ajouté des commentaires qui nous l'espérons vous aider à obtenir votre tête autour de l'ensemble adaptateur / adaptee / client / jargon Itarget - ce qui est un peu déroutant:

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 freddie = new EnglishMan(translator);

        // Freddie greets Tokyo, though he doesn't know a word of Japanese
        Console.WriteLine(freddie.Greetings()); //  "teo torriatte!"

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

        // Brian greets the crowd in Paris, though he doesn't know a word in French
        Console.WriteLine(brian.Greetings()); 
          // "So très charmant my dear! 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!!";
        }
    }
}
  

Un exemple très simple ...

 interface ITarget
    {
      List<string> GetProducts();
    }


    public class VendorAdaptee
    {
       public List<string> GetListOfProducts()
       {
          List<string> products = new List<string>();
          products.Add("Gaming Consoles");
          products.Add("Television");
          products.Add("Books");
          products.Add("Musical Instruments");
          return products;
       }
    }


    class VendorAdapter:ITarget
    {
       public List<string> GetProducts()
       {
          VendorAdaptee adaptee = new VendorAdaptee();
          return adaptee.GetListOfProducts();
       }
    }


    class ShoppingPortalClient
    {
       static void Main(string[] args)
       {
          ITarget adapter = new  VendorAdapter();
          foreach (string product in adapter.GetProducts())
          {
            Console.WriteLine(product);
          }
          Console.ReadLine();
       }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top