java - 在接口中创建具体实现的新实例 - 这是反模式吗?
问题描述
假设我有两个不同实现类的接口,AuthorDao
例如.MyAuthorDaoImpl1
MyAuthorDaoImpl2
在我的界面AuthorDao
中,我有一些基本的 crud 方法和一个额外的方法,static
用于获取MyAuthorDaoImpl1
.
它看起来像这样:
public interface AuthorDao {
void methodA();
void methodB();
...
static MyAuthorDaoImpl getInstance() {
return new MyAuthorDaoImpl1();
}
}
问题
- 这种静态方法
getInstance()
不是反模式吗?因为在我看来,我们的接口不应该依赖于具体的实现类,但是我的朋友说没关系,他很确定,这应该是这样工作的。他说这是工厂方法。 - 他说我们可以通过构造函数创建这个接口的实例,我们不必使用这个
static
方法,所以这没什么不好。真的吗,这没什么不好?我认为这是紧耦合的例子,接口不应该依赖于具体的实现,但他说事实并非如此。 - 他说这和课堂上的情况一样
Calendar
,因为也有getInstance()
方法。
编辑
此外,在他看来,如果我们决定更改MyAuthorDaoImpl1
为MyAuthorDaoImpl2
. 因为唯一的变化是getInstance()
方法。
解决方案
这个实现是一个循环依赖,大致如下:
MyAuthorDaoImpl
虽然它可能会在 Java 中工作,但想象一下,如果您以后决定实现时不再包含该类会发生什么ABetterAuthorDaoImpl
。现在您必须更改界面。在这种情况下,这是一个微小的变化,但可以在更大的范围内想象它。
通常,工厂方法返回接口类型而不是实现类型。例子:
class AuthorDaoFactory {
static AuthorDao getInstance() {
return new MyAuthorDaoImpl1();
}
}
这避免了循环依赖,如下图所示:
您会注意到依赖项中没有循环路径。对于这个简单的示例,这可能无关紧要,但是如果您的工厂方法创建了一个基于配置动态加载的类的实例呢?这是控制反转 (IoC) 的一个常见示例,通常用于执行诸如为不同硬件提供通用接口之类的操作。实现隐藏在接口后面。
您会注意到 JavaCalendar
类方法getInstance
返回 type Calendar
。底层实现可能是特定于语言环境的。如果您查看 Java 文档中对该方法的描述,它会说:
获取使用默认时区和语言环境的日历。返回的日历基于具有默认语言环境的默认时区中的当前时间。
那么具体的实现方式是什么?你不知道也不在乎,你只知道它是 type Calendar
。
推荐阅读
- java - 使用 Apache POI 基于 csv 工作表更新 Excel 工作表值
- javascript - 如何让 elevateZoom 处理多个图像
- c# - PrintWindow 出现黑屏
- html - CSS多个不同位置:绝对按钮屏幕分辨率问题
- jquery - jqGrid 在搜索中仅显示“IsNull”和“Is Not Null”选项
- plugins - 在 Cumulocity 的 Cockpit 仪表板中识别小部件的删除
- ios - FBAudienceNetwork 在 iOS 项目中抛出 libc++abi.dylib 异常
- javascript - Mojo::UserAgent 和 JavaScript
- typescript - 打字稿将数据发送到服务器
- python - 模型继承还是外键?