我试图在Java中使用接口,抽象类和泛型构建一个相当复杂的结构。由于没有仿制药的经验,只有平均创建优质OOP设计的经验,这开始证明是一个很大的挑战。
我有一种感觉,我正在尝试做的事情实际上无法完成,但我可以接近它。我会尽量简短地解释一下。我只想告诉我这个结构将代表我的DAO和服务层来访问数据库。使这个问题更抽象只会使其更加困难。
我的DAO图层完全没问题。有一个通用的DAO接口,每个实体都有一个DAO接口,它扩展了泛型接口并填充了泛型类型。然后是每个DAO实现扩展的抽象类,它实现相应的接口。最有可能令人困惑的阅读,所以这里是以产品的DAO为例的图表:
现在,对于服务类,我有一个类似的结构。无论如何,服务类中的大多数方法都映射到DAO方法。 如果您将上图中的每个“DAO”替换为“服务”,您将获得我的服务层的基础。但根据我的以下想法,我有一件事要做:
实体的每个服务类至少会访问一个DAO对象,即它所针对的实体的DAO。
哪个是......
如果我可以为使每个服务类为其各自实体的DAO对象设置一个实例变量,那么我的服务层将是完美的,在我看来。 如果我的设计看起来不那么好,欢迎提出建议。
我已经像这样实现了它:
public abstract class AbstractService<EntityDAO> {
EntityDAO entityDAO;
public AbstractService() {
entityDAO = makeEntityDAO(); //compiler/IDE warning: overridable method call in constructor
}
abstract EntityDAO makeEntityDAO();
}
public class ProductServiceImpl extends AbstractService<ProductDAOImpl> {
public ProductServiceImpl() {
super();
}
@Override
ProductDAOImpl makeEntityDAO() {
return new ProductDAOImpl();
}
}
此设计的问题是我不喜欢的编译器警告:它在构造函数中有一个可覆盖的方法调用(请参阅注释)。现在设计可以覆盖,实际上我强制执行确保每个服务类都引用相应的DAO。这是我能做的最好的事情?
我尽我所能包含您可能需要的所有内容,并且只包含您对此问题所需的内容。我现在要说的是,欢迎提出意见并提供更广泛的答案,感谢您花时间阅读。
答案 0 :(得分:3)
首先注意一点:例如,通常在以Presentation / Service / DAO等层组织的应用程序中,您有以下规则:
这将提供更简单的测试,更好的代码封装,以及不同层的更清晰定义(通过易于识别为公共API的接口)
也就是说,有一种非常常见的方法可以以最灵活的方式处理这种情况:dependency injection。 Spring是依赖注入(以及许多其他事情)的行业标准实现
这个想法(简而言之)就是你的服务会知道它需要一个IEntityDAO, 某人 会在实际使用之前注入并实现界面服务。 某人 称为IOC容器(Inversion of Control容器)。它可以是Spring,它的作用通常由应用程序配置文件描述,并将在应用程序启动时完成。
重要提示: 这个概念很棒而且功能强大,但简直就是愚蠢。您还可以使用Inversion of Control架构模式,而不需要框架,其中包含一个非常简单的实现,其中包含一个“组装”应用程序部件的大型静态方法。但在工业环境中,最好有一个框架,允许注入其他东西,如数据库连接,Web服务存根客户端,JMS队列等......
优点:
示例java代码:
public abstract class AbstractService<IEntityDAO> {
private IEntityDAO entityDAO; // you don't know the concrete implementation, maybe it's a mock for testing purpose
public AbstractService() {
}
protected EntityDAO getEntityDAO() { // only subclasses need this method
}
public void setEntityDAO(IEntityDAO dao) { // IOC container will call this method
this.entityDAO = dao;
}
}
在spring配置文件中,你会有类似的东西:
<bean id="ProductDAO" class="com.company.dao.ProductDAO" />
[...]
<bean id="ProductService" class="com.company.service.ProductService">
<property name="entityDAO" ref="ProductDAO"/>
</bean>