Java服务体系结构

Java服务体系结构,java,architecture,Java,Architecture,我想设计一个API,它读取一个大文本文件,提取相关信息,并返回一个Foo对象列表,如下所示: interface FooService { Optional<Foo> getFoo(Bar bar); } 这是一个合理的API设计还是有更好的方法来实现我的目标?也就是说,用InputStream调用超级构造函数是明智的,还是最好有一个单独的load()方法在需要时打开流?我不明白为什么需要那个抽象基类。偏好组合而非继承;我认为更合理的解决办法是: public class

我想设计一个API,它读取一个大文本文件,提取相关信息,并返回一个Foo对象列表,如下所示:

interface FooService {
    Optional<Foo> getFoo(Bar bar);
}

这是一个合理的API设计还是有更好的方法来实现我的目标?也就是说,用InputStream调用超级构造函数是明智的,还是最好有一个单独的
load()
方法在需要时打开流?

我不明白为什么需要那个抽象基类。偏好组合而非继承;我认为更合理的解决办法是:

public class FooServiceImpl implements FooService { 
...
然后是客户,比如

public class UrlFooService implements FooService {
  private final FooService delegatee;

 public  UrlFooService(URL url) {
    delegate = new FooServiceImpl(url.openStream())
 ...
 @Override
 Optional<Foo> getFoo(Bar bar) { return delegatee.getFoo(bar); }
公共类UrlFooService实现FooService{
私人最终服务委托人;
公共UrlFooService(URL){
delegate=new FooServiceImpl(url.openStream())
...
@凌驾
可选的getFoo(Bar){return delegatee.getFoo(Bar);}
继承将您的具体服务类与该父类相耦合;我更希望通过使用这种简单的“委托人”机制来避免这种情况


请注意:我还更改了UrlSerivce的ctor以获取URL。您已经有了URL类型,那么为什么还要麻烦自己调用新的呢?这只意味着您的UrlService将不得不处理所有可能出现错误的事情!

您的问题在这里有一些挑战,我将首先分析一下pro这个问题有点不同

正如@sisyphus所说的,注意你在构造函数中所做的那些事情。一个构造函数真的应该只关注于创建一个“有效对象”而不是别的。来自@GhostCat的很多好主意也是如此

相反,请考虑按如下方式对问题进行建模:

创建一个接口,表示您的服务的API。在这种情况下,如果您希望它是“GETFACE()),那么很棒。考虑您想传递的内容(是文件还是URL或路径)。既然你说它是一个大文件,那么在内存中实例化一个大对象并再次将其解析为有用的格式可能不是一个好主意。你肯定要为垃圾收集付出代价

接下来,您应该考虑将文件的“查找”分离出来,或者使用解析逻辑打开流。在尝试打开文件时,可能会出现很多异常,从找不到文件、没有权限到打开的文件过多(ulimit)

当谈到解析时,我建议你考虑清楚你正在分析什么,以及什么。如果这是一个现实世界的问题,“稳定格式”总是会发生变化——尤其是在容忍“无效”格式时,比如其他非打印字符的存在或意外的EOF。有很多要求优雅地处理事情,还需要了解解析内容的统计信息、有哪些错误以及如何处理这些错误


我的2美分。

有关工作代码,请转到codereview.stackexchange.com在构造函数中工作通常是个坏主意。这会导致代码测试困难,并可能导致继承层次结构中出现不明显的行为。
public class FooServiceImpl implements FooService { 
...
public class UrlFooService implements FooService {
  private final FooService delegatee;

 public  UrlFooService(URL url) {
    delegate = new FooServiceImpl(url.openStream())
 ...
 @Override
 Optional<Foo> getFoo(Bar bar) { return delegatee.getFoo(bar); }