Pra*_*mar 3 c# design-patterns
我只是设计模式的入门者,刚刚学习了理论定义以及如何在代码中实现,但喜欢了解各种鼓励使用Adapter模式的现实情况/案例/场景。
感谢C#中的示例。
假设您有一个解析HTML文件以确保它们有效的类。看起来像这样:
public class Parser
{
public Parser(string filePath)
{
...
}
public void Parse()
{
...
}
public bool IsValid()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
假设您正在应用程序中使用它。应用程序代码可能如下所示:
Parser p = new Parser("file.html");
p.Parse();
if(p.IsValid())
print "yay"
else
print "lame"
Run Code Online (Sandbox Code Playgroud)
您编写了Parser
该类,效果很好,但是您的朋友写了另一个效果更好的课程。假设他们的课程如下:
public class BetterParser
{
public bool ParseHtml(FileStream fs)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您想使用朋友的BetterParser
类而不是您的Parser
类,但是它实际上不适用于您的代码,因为它具有不同的方法名称和稍有不同的工作方式。您可以将上面的应用程序代码更改为如下所示:
FileStream fs = GetStream("test.html")
BetterParser bp = new BetterParser()
if(bp.ParseHtml(fs))
print "yay"
else
print "lame"
Run Code Online (Sandbox Code Playgroud)
很好,但是,如果您有一个大型应用程序,并且在Parser
任何地方都使用您的类,那该怎么办?您可能并不真的想去更改使用它的所有位置,因为这将需要大量额外的测试和潜在的错误。
您可以做的是使用适配器模式来更改您的类,以在其实现中实际使用您朋友的类。
class Parser
{
private BetterParser bp = new BetterParser();
private FileStream fs;
private boolean successful;
public Parser(string file)
{
fs = GetStream(file);
}
public void Parse()
{
successful = bp.ParseHtml(fs);
}
public boolean IsValid()
{
return successful;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以看到,现在班级的实现在后台使用了您朋友的班级。因此,现在无需更改使用Parser类的所有代码,您仍然可以获得使用更好的解析器的好处。
这基本上就是适配器模式的全部内容。它连接了两个无法直接相互连接的事物。在这种情况下,Parser类曾经是普通的HTML解析器,但是它变成了将您的应用程序代码连接到您朋友的解析器的适配器。
这是关于将接口与实现分开的。您的应用程序代码不应依赖解析器类在内部的工作方式,而必须依赖于该类的接口。该类具有一个采用文件路径的构造函数,该类具有一个Parse
不带参数的方法,以及一个IsValid
返回布尔值的方法。这些都是类的接口的所有方面,如果该接口发生更改,那么您的应用程序也无法在不进行更改的情况下使用该类。因此,您可以保持接口不变并更改实现。
比班级还大
人们经常说适配器只是另一个类的“包装器”。在代码级别的适配器上,很多时候可能都是这样。但是,整个应用程序也可以充当适配器。假设您有一些服务器提供了一些XML Web服务API(即SOAP)。这意味着与之交谈的所有客户端都需要了解XML。如果您想挂接一个不使用XML(也许使用JSON)的客户端,该怎么办?一种选择是在服务器和JSON框之间放置一个框。这个新框将充当可在XML和JSON之间转换的适配器。客户端使用JSON与适配器对话,适配器使用XML与服务器对话。