我对适配器类没有什么疑问。我知道适配器类的目标是什么。何时应该使用。我怀疑是关于班级建设。我已经检查了一些教程,并且所有人都说我应该将“Adaptee”类作为依赖项传递给我的“Adapter”。 e.g。
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();
}
}
您有什么看法?
答案 0 :(得分:8)
我想说,当涉及到复杂的对象时(除了类是Builder
或Factory
之外),你应该总是避免类中的new运算符,以减少耦合并使代码更好测试。可以在类方法中构造像List或Dictionary或值对象这样的课程对象(这可能是类方法的目的!)
让我们举例来说,你的AdapteeClass是Remote Proxy
。如果您想使用单元测试,您的单元测试必须使用真正的代理类,因为在单元测试中无法替换它。
如果您使用第一种方法,则在运行单元测试时可以轻松地将模拟或假冒注入构造函数中,以便您可以测试所有代码路径。
Google有guide on writing testable code更详细地描述了这一点,但有些重点是:
不可测试代码的警告标志
- 构造函数或字段声明中的新关键字
- 构造函数或字段声明中的静态方法调用
- 除了构造函数中的字段赋值之外的任何内容
- 构造函数完成后对象未完全初始化(注意初始化方法)
- 构造函数中的控制流(条件或循环逻辑)
- 代码在构造函数中执行复杂的对象图构造,而不是使用工厂或构建器
- 添加或使用初始化块
答案 1 :(得分:1)
AdapteeClass
可以有一个或多个非平凡的构造函数。在这种情况下,您需要在SampleAdapter
构造函数中复制所有这些内容以具有相同的灵活性。传递已构造的对象更简单。
答案 2 :(得分:0)
我认为在Adapter中创建Adaptee是有限的。如果有一天你想要调整预先存在的实例怎么办?
说实话,如果可能的话,我会做两件事。
Class SampleAdapter implements MyInterface
{
private AdapteeClass mInstance;
public SampleAdapter()
: base (new AdapteeClass())
{
}
public SampleAdapter(AdapteeClass instance)
{
mInstance=instance;
}
}
答案 3 :(得分:0)
假设您有一个带有常规 USB 端口的外置硬盘,并且您正尝试将其连接到只有 type-c 端口的 Mac。是的,您可以购买一个带有 type-c 端口的新驱动器,但是里面的数据呢?
适配器模式也是如此。有时您会用大量的口味初始化 AdapteeClass。进行转换时,您希望保留所有上下文。