在我的日常编程中,我尽量遵循可靠的原则和其他设计模式,但在某些情况下会变得困难,特别是使用依赖倒置原则,对于层次结构类,创建工厂类并在那里存储对象可能很容易,也与 singleton 或 builder 相同,但是当您在方法中使用单个类对象时会出现问题,该方法会不时更改并且同样没有层次关系
//这里在 newTaskFor() 方法中,浸入原则被违反了 那么如何在日常程序中解决此类问题,或者在容器类中使用 new Keyword 是可以的
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable); //violating Dip principle
}
/**
* @throws RejectedExecutionException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
答案 0 :(得分:0)
在某个时间点总有凝结物。如果您想对所有内容应用 DIP,那么几乎所有类型都必须一遍遍地隐藏在高级特定接口后面,这不切实际。
例如,声明 newTaskFor
的高级模块可以很好地制作自己的 Future
抽象,这些抽象不会直接耦合到 Java 的本机 API,但这可能会很多工作收益微乎其微?
我经常问自己这个问题的一个很好的例子是,当我设计了一个简单的网络爬虫库时,它必须大量操作 HTML 文档。我可以选择耦合到像 Jsoup 这样的特定库,或者创建我自己的抽象以避免紧密耦合。由于我必须在最后支持复杂的文档查询和操作,我发现在 Jsoup 之上制作另一个抽象层非常不切实际,我必须重新定义几乎所有节点接口。
在这些情况下有效抽象的关键是只关注系统真正需要的 API 部分,其余部分并确保以特定于域的方式表达该抽象。如果您最终模仿整个 API,那么无论如何您的抽象很可能会受到特定实现的高度影响。 如果您发现需要底层库的所有功能,那么将其抽象出来可能代价太大。
编辑:
我刚刚检查了一下,似乎我在第三段中撒了谎,最终我制作了一个如下所示的 API(几年前,我似乎只支持我拥有的最小用例而不是复杂的库),但老实说,Scraper
只会支持极其基本的提取,而这种抽象最终可能弊大于利。