了解适配器模式

我试图了解适配器模式及其在现实世界中的使用。 在浏览了互联网和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(); } } 

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

假设我想模拟一个没有实现接口的框架类(并且没有虚拟方法)。 有许多嘲弄的apis这很难或不可能做到。 那么,我要做的是将我自己的界面定义为我所定位的类的签名的子集。 我实现了一个实现此接口的包装类,并简单地将调用委托给包装的框架类。 此包装类用作框架类的适配器。 我的类使用此适配器而不是框架类,但获取框架类的行为。

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

还要考虑这样一种情况:你有几个不同的类,它们具有基本相同的function,但签名不同,你希望能够交替使用它们。 如果您无法转换这些(或者由于其他原因而不想),您可能希望编写一个定义公共接口的适配器类,并在该接口的方法和目标类上可用的方法之间进行转换。

框架类:

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

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

这个Bitmap有一个构造函数,可以让你从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) { ... } } 

您需要向Stream对象提供IStream接口:

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

我添加了评论,希望能帮助您了解整个适配器/适配器/客户端/ 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!" } ///  /// This is the client. ///  public class EnglishMan : ITarget { private ITarget target; public EnglishMan(ITarget target) { this.target = target; } public string Greetings() { return target.Greetings(); } } ///  /// The target interface ///  public interface ITarget { string Greetings(); } ///  /// This is the adaptor ///  public class JapaneseTranslator : ITarget { private JapaneseSpeaker japanese; public JapaneseTranslator(JapaneseSpeaker japanese) { this.japanese = japanese; } public string Greetings() { return japanese.Konnichiwa(); } } ///  /// This is the adaptee ///  public class JapaneseSpeaker { public JapaneseSpeaker() { } public string Konnichiwa() { return "Konichiwa, hisashiburi!"; } } ///  /// This is the adaptor ///  public class FrenchTranslator : ITarget { private FrenchSpeaker french; public FrenchTranslator(FrenchSpeaker french) { this.french = french; } public string Greetings() { return french.Bonjour(); } } ///  /// This is the adaptee ///  public class FrenchSpeaker { public string Bonjour() { return "Bonjour!!"; } } }