使用Adapter / Facade模式来预测不兼容的接口和复杂性?

时间:2015-10-02 03:18:45

标签: design-patterns adapter facade

维基百科中提到了适配器模式,用于修复预期接口和实际接口之间的不兼容性。

据说,Facade模式模糊了复杂的实现,并提供了一个简化的API。

然而,即使没有这些问题,这些模式是否会被使用? Aka,过早地使用这些模式以预期未来的不兼容性和复杂性?

我遇到过一个代码,其中包装类是使用内部类的接口的精确副本实现的 - 它具有原始的所有公共方法,具有完全相同的参数。包装类和内部类也在同一个程序集中定义。

像这样:

public class ClassifierImplementation
{
    private Classifier classifier_;
    public Wrapper() { classifier_ = new Classifier(); }

    public int[] Classify(double[] values, int seed)
    {
        return classifier_.Classify(values, seed);
    }

    // And other more public methods
}

这种实施背后的理由是什么?

2 个答案:

答案 0 :(得分:1)

我将一次使用分析1模式 -

  • 适配器模式上面给出的分类器示例看起来像一个适配器,因为它适应(通过对象适配器的经典定义)从ClassifierImplementation到Classifier - 但它并没有真正适应你提到的方法是相同的一种类型到另一种类型。因此,如果一切都一样 - 为什么要适应!!

  • 外观模式 - 它不是外观,因为外观是为了简化界面(在这种情况下是方法),而在这种情况下,方法/方法定义对于ClassifierImplementation和Classifier是相同的。 ClassifierImplementation似乎更像是一个包装器(正如你所提到的)而不是分类器,它将我带到了下一点 -

  • 代理模式 - 它看起来像是Proxy模式的一个实例,其中ClassifierImplementation正在尝试控制对它所持有的Classifier实例的访问。这样,分类器实现可以根据需要修改传入请求参数或传出返回值,并且方法定义不会更改。

最后,所有的说法和完成,ClassifierImplementation类应该重命名为更有意义的东西(如 ClassifierProxy ),因为它没有扩展或实现任何东西。当前名称会造成混淆并降低可读性。

注意 - ClassifierImplementation可以实现分类器正在实现的相同接口,但它更像是一个装饰器而不是代理。

答案 1 :(得分:1)

  

我遇到过一个代码,其中包装类是使用内部类的接口的精确副本实现的 - 它具有原始的所有公共方法,具有完全相同的参数。包装类和内部类也在同一个程序集中定义。

     

这种实施背后的理由是什么?

一个原因是创建一个包装类可以实现的抽象。

这方面的一个例子是ASP.NET中的HttpContext类。最初的ASP.NET实现是一个名为HttpContext的类,它有一个非常大而复杂的接口。

当单元测试进入场景时,很快发现仅为单元测试创​​建此类的实例并不是很实用,因为类本身具有多个依赖项和无法设置的只读属性。 / p>

因此,在.NET的更高版本中,HttpContextBase抽象类的创建与HttpContext完全相同。此外,它附带了一个名为HttpContextWrapper的具体实现,它将HttpContext实例作为构造函数参数。

现在,测试更容易,因为测试中的代码只需要依赖HttpContextBase。为了满足被测代码的逻辑,很容易使用模拟库一次定义几个属性。

实时应用程序通常会注入HttpContextWrapper,因为它与HttpContext具有完全相同的接口,它与非可模拟的HttpContext类完全相同在生产中。

具有相同的接口意味着要使现有代码可测试,只需将变量或参数引用从HttpContext更改为HttpContextBase,其他代码都不需要更改。