鉴于我有一个使用某种搜索器来获取和显示URL列表的类,如下所示:
package com.acme.displayer;
import com.acme.searcher.SearcherInterface;
class AcmeDisplayer {
private SearcherInterface searcher;
public AcmeDisplayer(SearcherInterface searcher) {
this.searcher = searcher;
}
public void display() {
List<String> urls = searcher.getUrls();
for (String url : urls) {
System.out.println(url);
}
}
}
而SearcherInterface
如下所示:
package com.acme.searcher;
public interface SearcherInterface {
List<String> getUrls();
}
这些搜索者有多种实现方式。 (例如,一个只返回一个硬编码的String
s列表用于测试目的)。
但是,另一个会对任何API执行HTTP请求并解析URL的响应,如下所示:
package com.acme.searcher.http;
import com.acme.searcher.SearcherInterface;
public class HttpSearcher implements SearcherInterface {
private RequestPerformerInterface requestPerformer;
private ParserInterface parser;
public HttpSearcher(RequestPerformerInterface requestPerformer, ParserInterface parser) {
this.requestPerformer = requestPerformer;
this.parser = parser;
}
List<String> getUrls() {
InputStream stream = requestPerformer.performRequest();
return parser.parse(stream);
}
}
由于关注点分离,完成了对这种HTTP请求的拆分。
然而,这导致了一个问题:Parser
可能只针对某个API构建,该API由某个RequestPerformer
表示。所以他们需要兼容。我现在已经摆弄了这种结构的泛型类型,即有一个TypeInterface
,HttpSearcher
s构造函数的两个参数都应该实现,但我没有让它工作......另一种方法是在一个类中实现一个检查如果另一个与它兼容,但这看起来很难看。
有没有办法通过他们正在处理的API实现RequestPerformer
s和Parser
s这样的分组?或者架构本身有什么问题吗?
你的HttpSearcher
看起来像是将这两个组合在一起的设备。您可以创建一个返回HttpSearcher
和其他类的工厂类,并将该工厂编码为将兼容的RequestPerformer
s和Parser
s组合在一起。
我之所以不建议利用类型系统,例如通过泛型,InputStream
类型可以保证它所拥有的数据的格式/类型。分离获取原始数据和解析的责任似乎是一个好主意,但您仍然必须“手动”将兼容类型组合在一起,因为只有您知道InputStream
将保留的数据格式/类型。