适配器模式和依赖关系



我对适配器类没有什么疑问。我知道适配器类的目标是什么。以及何时应该使用。我怀疑的是阶级建设。我查看了一些教程,它们都说我应该将"Adaptee"类作为依赖项传递给我的"Adapter"。例如

Class SampleAdapter implements MyInterface
{
    private AdapteeClass mInstance;
    public SampleAdapter(AdapteeClass instance)
    {
         mInstance=instance;
    }
}

这个例子是从维基百科上复制的。正如您所看到的,AdapteeClass是作为依赖项传递给我的对象的。问题是为什么?如果我正在更改一个对象的接口,很明显我将使用"新"接口,而不需要"旧"接口。为什么我需要在适配器之外创建"旧"类的实例。有人可能会说我应该使用依赖注入,这样我就可以传递我想要的任何东西,但这是适配器——我需要更改具体类的接口。就我个人而言,我认为下面的代码更好。

Class SampleAdapter implements MyInterface
{
    private AdapteeClass mInstance;
    public SampleAdapter()
    {
         mInstance= new AdapteeClass();
    }
}

你的意见是什么?

我想说的是,当涉及到复杂对象时(除了类是BuilderFactory时),您应该始终避免类中的新运算符,以减少耦合并使代码更好地可测试。像List或Dictionary这样的非常规对象或值对象可以在类方法中构造(这可能是类方法的目的!)

例如,假设AdapteeClass是一个Remote Proxy。如果你想使用单元测试,你的单元测试必须使用真正的代理类,因为在单元测试中没有办法替换它。

如果使用第一种方法,那么在运行单元测试时,可以很容易地将mock或false注入构造函数,这样就可以测试所有代码路径。

谷歌有一个关于编写可测试代码的指南,其中更详细地描述了这一点,但一些要点是:

不可测试代码的警告标志

  • 构造函数或at字段声明中的new关键字
  • 构造函数或at字段声明中的静态方法调用
  • 构造函数中除了字段赋值之外的任何内容
  • 构造函数完成后未完全初始化对象(请注意初始化方法)
  • 构造函数中的控制流(条件或循环逻辑)
  • 代码在构造函数中进行复杂的对象图构造,而不是使用工厂或生成器
  • 添加或使用初始化块

AdapteeClass可以有一个或多个非平凡构造函数。在这种情况下,您需要在SampleAdapter构造函数中复制所有它们,以具有相同的灵活性。传递已构造的对象更简单。

我认为在Adapter中创建Adaptee是有限制的。如果有一天你想修改一个预先存在的实例,该怎么办?

不过,老实说,如果可能的话,我会两者都做。

Class SampleAdapter implements MyInterface
{
    private AdapteeClass mInstance;
    public SampleAdapter()
       : base (new AdapteeClass())
    {
    }
    public SampleAdapter(AdapteeClass instance)
    {
         mInstance=instance;
    }
}

让我们假设您有一个带有常规USB端口的外部硬盘驱动器,并且您正试图将其连接到只有type-c端口的Mac。是的,你可以买一个有c型端口的新驱动器,但里面的数据呢?

适配器模式也是如此。有时初始化AdapteeClass时会用到大量的味道。进行转换时,需要保留所有上下文。

最新更新