了解适配器模式

c# design-patterns adapter

27227 观看

4回复

1043 作者的声誉

我试图了解适配器模式及其在现实世界中的使用。在浏览了Internet和www.dofactory.com上的各种文章之后,我创建了此示例代码。我只想知道我的理解是否正确。在下面的示例中,我在Adapter类中创建了MSDAO对象。后来我将其更改为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();
  }
}
作者: pradeeptp 的来源 发布者: 2009 年 8 月 19 日

回应 4


78

443949 作者的声誉

决定

通常,适配器模式将一个接口转换为另一个接口,但是它可以简单地包装行为以将您的类与基础实现隔离。在您的情况下,您正在使用适配器,但是您可以轻松地定义DAO对象以简单地实现接口并针对该接口进行编程。当您无法控制目标类时,通常使用适配器模式。适配器模式的主要用途是为未实现接口的框架类创建包装器。

假设我想模拟一个没有实现接口(并且没有虚拟方法)的框架类。使用许多模拟API很难或不可能做到。然后,我要做的是将自己的接口定义为我要定位的类的签名的子集。我实现了一个包装器类,该包装器实现了此接口,并仅将调用委派给包装的框架类。该包装器类用作框架类的适配器。我的类使用此适配器而不是框架类,但是得到了框架类的行为。

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

还考虑以下情况:您有几个具有基本相同功能,但签名不同并且希望能够互换使用的不同类。如果您无法转换这些(或由于其他原因而不想转换),则可能需要编写一个适配器类来定义一个通用接口,并在该接口的方法和目标类上可用的方法之间进行转换。

框架类:

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

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

适合他们的适配器

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

然后用作:

ITargetAdapter adapter = new AdapterA( new TargetA() );
adapter.Open();
adapter.Close();     
作者: tvanfosson 发布者: 2009 年 8 月 19 日

3

129111 作者的声誉

System.Drawing.Bitmap该类中存在一个.NET框架内的规范示例。

该位图具有一个构造函数,可让您从加载图像Stream

public Bitmap(
    Stream stream
)

您所不知道的是,.NET Bitmap类在内部是GDI + Bitmap类的包装器,其构造函数采用了IStream

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

因此,在C#世界中,当我调用时:

new Bitmap(stream);

它必须转身并致电:

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

问题是如何将.NET Stream对象呈现给需要COM IStream接口的方法。

因此内部GPStream类:

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

您需要为IStream您的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)
...                                         ...

所以现在您有了一个适配器:

在此处输入图片说明

代码类似于:

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

GdipCreateBitmapFromStream(stm, out gpBitmap);
作者: Ian Boyd 发布者: 2017 年 7 月 11 日

3

15872 作者的声誉

我添加了评论,这些评论有望帮助您掌握整个Adaptor / adaptee / client / Itarget行话-这有点令人困惑:

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!!";
        }
    }
}
作者: BKSpurgeon 发布者: 2017 年 9 月 28 日

0

171 作者的声誉

一个非常简单的例子

 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();
       }
    }
作者: Neeraj Singh Chouhan 发布者: 2019 年 9 月 17 日
32x32