架构:操纵模型而不污染POJO的最佳实践?并且无需在任何地方重复锅炉板代码

时间:2012-01-23 15:59:31

标签: java design-patterns architecture software-design

这是我们经常遇到的问题。必须有一些最佳实践来解决这个问题......

简化问题

哪里是放置操纵POJO的通用代码的最佳位置?

这样:

  • POJO只有属性和getter / setter
  • 相同的模型操作代码不会重复“无处不在”
  • 非常清楚哪些类负责操纵模型

背景

我们有一个定义我们域名的架构。从那时起,我们生成一个“纯”模型,它由来自JAXB的简单对象(PO​​JO)组成。

在使用此模型时,团队中的几位开发人员已创建了用于访问和操作模型的样板代码。它在许多地方“撒了”。有些人创建了包装器对象,它们继承了模型的实例并添加了功能。其他人创建了外部实用程序类。我正在寻求统一这个代码,以便它不再“洒在各处”。 理想情况下,逻辑可以包含在某类对象中,这些对象明确负责模型的通用操作。

实施例

让我们使用杂货店作为一般例子。模型对象包括以下内容:
Products, Aisle, Shelf, Employee, WorkSchedule, Vendor

常见的模型操作包括:
findManagerWorkingOnDay(day, schedule), findAisleForProduct(apples), countItemsOnShelf(topShelf), product.isModified(), removeProductFromVendor(apples, vendor)

我们不希望使用removeProductFromVendor之类的功能“污染”我们的供应商POJO。同样,我们不一定要扩展每个模型对象,只是添加isModified属性,这样我们的GUI就可以知道“启用/禁用”保存按钮。

或者我们呢?

摘要

一旦模型对象在内存中,谁应该负责操纵它 - 例如,迭代一个“今天值班的员工”列表并找到一个“经理人”?

在这些情况下,数据库调用过度,因为我们已经在内存中拥有了所需的一切(例如:我们已经查询过DataStore,我们需要在整个应用程序中使用结果对象)。 理想情况下,此代码可供具有员工列表的任何对象使用。


就最佳实践而言,静态方法的理想位置在哪里:
public static Employee findManager(List<Employee> employeesOnDuty);

将迭代员工列表(POJO)并返回第一个employee.title.toLowerCase().contains("manager")

如果团队使用此示例对象模型,则有几个人会编写这样的函数。有哪些最佳实践可以捕捉到这一责任,这样POJO仍然是“纯粹的”,并且相同的锅炉板代码不会“随处散布”。

5 个答案:

答案 0 :(得分:6)

鉴于您的POJO对象来自供应商,我理解您不愿意为他们添加功能,并且您显然不希望代码随机散布在您的项目周围。

对于一组装饰器子类或者Ken建议的外墙来说,听起来像是一个工作。

我喜欢这里的装饰器,因为你只需要通过装饰器类的名称来引用你的供应商pojo,然后在一个地方添加行为(isModified,searchByName等)。

答案 1 :(得分:5)

据我所知,听起来你的POJO模型只是数据(或者你想保持这种方式)。为什么不创建外观对象,如QueryCount或其他命名的功能分组,它隐藏了操作算法的所有相关机制?

它不会污染 POJO,这听起来是你想要避免的。

答案 2 :(得分:3)

尽管问题是在1岁的时候,但希望它对其他人有帮助。 因此,愿意保留POJO并单独行为,以便这些陈述有:  a)POJO只有属性和getter / setter,  b)重用相同的模型操作代码,  c)很清楚哪些类负责操纵模型 通过将应用程序拆分为层,得到广泛认可正在实现,即:

  1. 您的POJO - 是普通模型,包含字段/属性,只是getter / setter;
  2. 将关于模型操作的业务逻辑放入服务层 - 在您的情况下,所有与操作相关的操作都在例如Employee可以在EmployeeService中分配(因此可以在很多地方重用);
  3. 与持久性相关的所有内容都转到DAO层,例如: EmployeeDAO;
  4. 用于在层之间交换数据,例如视图和服务 - 可以使用DTO(数据传输对象)。
  5. 如果将业务逻辑放入模型bean中,这就是所谓的域驱动设计 - 人们会在这里和那里询问它(我个人并不是域驱动设计的崇拜者)。

    希望,这有帮助。

答案 3 :(得分:2)

在类似的情况下,我们决定将所有“功能”(行为)推广为对象模型的一等公民。

所以我们现在有了不同的包,一个只有POJO,另一个是我们在这些对象上有函数对象(也就是处理器)的函数。

例如,Contract对象作为POJO,ContractBilling,ContractFinder,ContractCloser等作为处理器。他们中的大多数是根据合同或合同清单运作。

我们发现它非常有效,这迫使我们正确记录系统中的所有内容(因为函数已成为对象)。这种方法的架构优势非常棒,即使我们在这个设计中有更多的对象,我们也有更小的类更易于管理,易于理解和易于发展。

答案 4 :(得分:0)

我想对于像find这样的操作,它们属于服务类;但对于'isModified',服务类不会有帮助,它必须在pojo本身,除非当然通过服务类进行修改。然后,相应的服务类可以在集合中维护此类对象的状态。