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