设计模式 - 类数据职责



我有一个'采购订单'类。它包含有关单个采购订单的信息。我有一个用于数据库方法的 DAO 类。

加载和更新采购订单的方法的责任应驻扎在哪里?

PurchaseOrder 类应该具有直接使用 DAO 类的".

update"、"insert"、"delete"和".load"方法,还是 PurchaseOrder 类应该对 DAO 方法一无所知,并且应该有一个管理这些交互的 POController 类?

用户一次只能处理一个采购订单。

谢谢!

采购订单应该不知道其持久性的细节。这就是拥有某种数据访问层的意义所在,它处理对象的管理,并且对象本身可以专注于仅作为采购订单。

这也使系统更易于测试,因为您可以创建模拟采购订单并测试系统如何处理它们的逻辑,而不会纠缠于持久性问题。

我会通过使 PurchaseOrder 成为一个接口并将所有 DAO 代码放入实现中来保持简单,然后使用工厂。

这取决于您认为您的应用程序将存在多长时间。我公司的金属切削应用自1985年以来一直在不断发展,并通过计算机体系结构的多次变化进行了移植。在我们的例子中,我们几乎总是把东西推到接口(或使用你的术语的控制器类)后面,因为我们不知道5年、10年、15年后的事情会是什么样子。

通过使用控制器类,我们可以更改底层 API,而不会篡改上面的业务逻辑和 UI 调整级别。这些级别代表多年的工作,因此保持其行为很重要。

请记住,您的项目生命周期的大部分时间都在维护中。您现在为以后更轻松地更改设计所做的任何事情都将在未来节省大量时间。

PurchaseOrder 类应该对 DAO 一无所知。 采购订单类应该表示数据本身,仅此而已。 使用控制器或服务管理器或任何您想要调用它的东西来使用 DAO 持久化/加载 PurchaseOrder 记录。 这为您的设计提供了最大的灵活性。 您有一个位置用于数据模型,一个位置用于存储/检索 PurchaseOrders 的业务逻辑(控制器),还有一个位置用于实际保留 PurchaseOrders。

让我带你了解一下我的推理:

类方法
基本原则:持久性是一种类行为,应该是一个类方法
你需要分离关注点,所以你把数据库的细节放在一个DAO类中,并从类中使用它来实现方法。
第一个问题:如果你需要支持不同的DAO集,你需要通过工厂创建它们。第二个问题:并非所有持久性行为都与类的实例特别相关。例如,列表和搜索方法:它们返回类列表,而不是类,并且不依赖于实例。所以它们基本上是静态方法。
第三个问题:你想支持这个类的继承。因此,持久性详细信息因父项而异。如果你有静态方法,这将是一个问题。

所以你继续

控制器
基本原则:持久性方法不属于单个类,它们更大,因此应该分开
再次需要分离关注点,因此您需要 DAO。这是一个 Utility 类,因此方法基本上都是静态的
第一个问题:如果你想支持多个持久性方法,你需要一个工厂来创建DAO。
第二个问题:您希望支持类的层次结构,因此不能使用静态类。您需要通过工厂生成控制器。
第三个问题:你为你的开发人员提供了一个过于复杂的API。
客户端代码示例:

PurchaseOrder po;
PurchaseOrderController poc;
poc = PurchaseOrderControllerFactory.Instance.Create();
po = poc.GetPurchaseOrder(42);
// do stuff
poc.SavePurchaseOrder(po);

然后我会从头开始。

从行为
开始基本原则:坚持不是一种行为。行为大于持久性。
在您的系统中,将有一个采购订单子系统。您的用户将只能在高级别(用例级别)与之交互。因此,这些方法将实现采购订单用例。这些方法将使用DAO,如果需要,通过工厂访问数据库并执行它们需要做的任何事情。
简而言之,您的采购订单基本上是一个DTO,一种传递数据的快速方法。它不应该有行为。
客户端代码示例:

// It could be a factory if needed.
PurchaseOrderSystem pos = new PurchaseOrderSystem(); 
List<PurchaseOrder> transacted;
transacted = pos.TransactPurchaseOrders(john, 23);
// Show transacted purchase orders or whatever...

我肯定会将"业务逻辑"(PurchaseOrder)与数据库交互/访问分开。如果您迁移到其他供应商等,您将更容易更改访问,而不会干扰业务实现,而且您将更容易避免向数据库访问层添加行为。

就个人而言,我会创建一个管理交互的对象。我不能提出强有力的理由来说明不将此逻辑放在 PurchaseOrder 类本身中,但创建此控制器对象将导致更松散耦合的对象。

这里要考虑的关键是您将来可能想要做什么。也许您想用另一个数据库替换您的数据库?这就是为什么您绝对应该将用于与数据库交互的代码与表示 PO 的类分开的原因。这是基本的责任分离,我希望你已经做到了。

现在的问题是:您是否希望第三个类(控制器)来管理 PO 和 DAO 类之间的交互?我认为这取决于您如何使 DAO 类的接口变得通用。如果 DAO 接口足够通用,您可以使用不同的存储机制为它编写插件替换,但不更改接口,那么我会让 PO 类与它交互。如果没有,那么我会写一个控制器类。

要考虑的另一件事是结构的其余部分。保存/加载从哪里启动?如果您要对 PO 进行大量操作(保存、加载、打印、发送给客户),那么拥有一个执行所有这些操作的控制器而不是将功能集成到 PO 类中可能是有意义的。它的优势是无需修改 PO 类即可添加 PO 操作。

最新更新