在某些情况下使用适配器模式

Pra*_*mar 3 c# design-patterns

我只是设计模式的入门者,刚刚学习了理论定义以及如何在代码中实现,但喜欢了解各种鼓励使用Adapter模式的现实情况/案例/场景。

感谢C#中的示例。

d51*_*512 7

假设您有一个解析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与服务器对话。