我试图理解适配器模式及其在现实世界中的用途。在浏览了互联网和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();
}
}
答案 0 :(得分:76)
通常,适配器模式将一个接口转换为另一个接口,但它可以简单地包装行为以将您的类与底层实现隔离开来。在您的情况下,您正在使用适配器,但您可以轻松定义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();
}
}
还要考虑这样一种情况,即您有几个不同的类具有基本相同的功能,但签名不同,并且您希望能够互换使用它们。如果您无法转换这些(或者由于其他原因而不想),您可能希望编写一个定义公共接口的适配器类,并在该接口的方法和目标类上可用的方法之间进行转换。
框架类:
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();
答案 1 :(得分:3)
.NET框架内的规范示例存在于System.Drawing.Bitmap
类中。
此Bitmap有一个构造函数,可让您从Stream
加载图像:
public Bitmap(
Stream stream
)
您不知道的是,.NET Bitmap
类内部是GDI + Bitmap
类的包装器,其构造函数采用IStream
:< / p>
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);
答案 2 :(得分:3)
我添加了评论,希望能帮助您了解整个适配器/适配器/客户端/ 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!!";
}
}
}
答案 3 :(得分:0)
一个非常简单的例子...
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();
}
}