java - 需要有关 java 中复杂结构的建议(DAO 和服务层链接/耦合)

标签 java oop design-patterns generics

简介

我正在尝试使用接口(interface)、抽象类和泛型在 Java 中创建一个相当复杂的结构。由于没有使用泛型的经验,在创建良好的 OOP 设计方面只有一般经验,这开始证明是一个相当大的挑战。

我有种感觉,我想做的事情实际上无法完成,但我可以接近它。我会尽量简短地解释一下。我只想直接告诉你,这个结构将代表我的 DAO 和服务层来访问数据库。让这个问题更抽象只会让它变得更难。

我的 DAO 层完全没问题。有一个通用 DAO 接口(interface),对于每个实体,都有一个扩展通用接口(interface)并填充通用类型的 DAO 接口(interface)。然后有一个由每个 DAO 实现扩展的抽象类,后者又实现相应的接口(interface)。很可能读起来很困惑,所以这里以产品的 DAO 为例:

Diagram showing the DAO implementation for Product entities

现在对于服务类,我有一个类似的结构。无论如何,服务类中的大多数方法都映射到 DAO 方法。 如果你用“服务”替换上图中的每个“DAO”,你就得到了我的服务层的基础。但是我想做一件事,基于我的以下想法:

Every service class for an entity will at least access one DAO object, namely the DAO of the entity that it is designed for.

这是...

问题/问题

如果我可以进行适当的 OO 设计以使每个服务类都为其各自实体的 DAO 对象拥有一个实例变量,在我看来,我的服务层将是完美的。 欢迎就此提出建议,以防我的设计不如看上去的那么好。

我是这样实现的:

类抽象服务

public abstract class AbstractService<EntityDAO> {

    EntityDAO entityDAO;

    public AbstractService() {
        entityDAO = makeEntityDAO(); //compiler/IDE warning: overridable method call in constructor
    }

    abstract EntityDAO makeEntityDAO();
}

类 ProductServiceImpl

public class ProductServiceImpl extends AbstractService<ProductDAOImpl> {

    public ProductServiceImpl() {
        super();
    }

    @Override
    ProductDAOImpl makeEntityDAO() {
        return new ProductDAOImpl();
    }
}

此设计的问题是我不喜欢的编译器警告:它在构造函数中有一个可覆盖的方法调用(请参阅评论)。现在它被设计为可重写的,事实上我强制执行它是为了确保每个服务类都有对相应 DAO 的引用。这是我能做的最好的事情吗?

我已尽最大努力包含您可能需要的所有内容,并且仅包含您对此问题所需的内容。我现在要说的是,欢迎评论,更广泛的回答,感谢您花时间阅读。

StackOverflow 上的其他资源

Understanding Service and DAO layers

DAO and Service layers (JPA/Hibernate + Spring)

最佳答案

首先要注意一点:通常在按层组织的应用程序中,例如 Presentation/Service/DAO,您有以下规则:

  • 每一层只知道紧接其下的层。
  • 它只通过它的接口(interface)知道它,而不是它的实现类。

这将提供更容易的测试、更好的代码封装以及对不同层的更清晰的定义(通过易于识别为公共(public) API 的接口(interface))

就是说,有一种非常通用的方法可以以最灵活的方式处理这种情况:dependency injection .和 Spring是依赖注入(inject)(以及许多其他事物)的行业标准实现

这个想法(简而言之)是您的服务将知道它需要一个 IEntityDAO,并且 某人 将在实际使用之前注入(inject)它和接口(interface)的实现服务。那个某人 称为 IOC 容器(Inversion of Control 容器)。可以是Spring , 它所做的通常由应用程序配置文件描述,并将在应用程序启动时完成。

重要说明: 这个概念非常出色和强大,但却非常简单愚蠢。您还可以在没有框架的情况下使用控制反转架构模式,其实现非常简单,其中包含一个大型静态方法“组装”您的应用程序部分。但在工业环境中,最好有一个允许注入(inject)其他东西的框架,如数据库连接、Web 服务 stub 客户端、JMS 队列等......

好处:

  • 您可以轻松地进行模拟和测试,因为类唯一依赖的是接口(interface)
  • 您有一个由一小组 XML 文件组成的文件,这些文件描述了您的应用程序的整个结构,当您的应用程序增长时,这真的很方便。
  • 这是一个被广泛采用的标准,并且为许多 Java 开发人员所熟知。

示例 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>

关于java - 需要有关 java 中复杂结构的建议(DAO 和服务层链接/耦合),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13239354/

相关文章:

java - 如何克服这种 java 语法,使 double 成为字符串?

java - 使用枚举来检索页面 bean

php - 不保存空行

c++ - 是抽象类还是纯虚(接口(interface))?

java - 答案对象和面向对象设计

c# - 如何设计这样的项目?

c# - 如何动态组合条件?

java - 在抽象类的扩展之间共享变量

java - 贾斯珀报告 : access custom data source

java - PowerMockRule 与 EasyMock 一起 NOT Moquito