当我必须为Web应用程序设计我的类时,我经常会遇到同样的问题。要求是: - 可维护(例如,没有复制粘贴) - 层完全分离(业务层不必知道使用数据层的哪个方法) - 高性能:不加载无用的数据。
首先,我有一张包含所有客户及其地址的表格: 代码:
Customer
--Id
--Name
--Address
----City
----ZC
----Street
现在我想要一张桌子(在另一页中)与我所有的顾客和他们购买的书籍,我有几个可能性:
1 /我创建了一个新课程:
代码:
CustomerWithBooks
--Id
--Name
--Books[]
----ID
----name
PRO:我只加载有用的数据 缺点:我在我的UI之后构建了我的课程,并且有复制粘贴。
2 /我将Books []添加到第一堂课。 PRO:一切都在同一个班级,它是可维护的 缺点:我没有加载地址。如果我不加载地址,我可以:延迟加载,但我真的不喜欢它,或者当我使用我的课时,我必须知道我的DAL调用了哪种方法,我不喜欢它。< / p>
3 /我使用继承: 代码:
ClientBase
--ID
--Name
ClientWithBooks : ClientBase
--Books[]
ClientWithAdress : ClientBase
--Address
PRO:真的很可靠,而且我没有加载任何数据 缺点:如果在一个UI中我想显示书籍和地址,我该怎么办?
4 / ??我希望有一个完美的解决方案
答案 0 :(得分:3)
假设我理解正确,您的选项1接近良好。顾客和书是完全不同的两件事。您希望这些数据/功能分离,并且不应从任何公共基类(您已经创建)继承。
作为“Con”你说:我在我的UI之后构建了我的课程,并且有复制粘贴。
在您需要处理客户和图书的页面上,您将使用客户对象和图书对象,可能还有图书集合对象。根据您的数据库/对象模型的设置方式,您可能正在处理其他对象以使客户获得他们购买的书籍。例如,客户可能同时购买一本或多本图书,这些图书与订单对象相关联,该对象引用了客户。所以,你可能会从
开始这些都不需要相互继承。现在,让我们说让客户购买的所有书籍都是你做的很多,而你想简化它。然后,您希望直接从Customer上获取Books集合,尽管您用来获取这些书籍的SQL查询仍然通过db中的Orders。您必须从您的对象模型开始(以及幕后的表格)准确地反映现实。即使这给你看似很多的课程,但最终还是更简单。你最终可能会得到一些继承,你可能不会。
答案 1 :(得分:1)
我会避免使用2和3,因为它会将您锁定在一个不能满足您需求的限制性层次结构中。正如您所指出的,可能存在您想要的任何组合,例如客户和他们的书籍,也可能是他们的地址,也可能是他们的订购历史。或许你可能想要一本书的客户列表。由于您的基础业务信息不是真正的层次结构,因此您应该尽量避免使对象模型不必要地分层。否则,你将构建一些限制因素,这些限制会让你在以后遇到很多麻烦,因为你现在无法想到所有的场景。
我认为你正站在正确的轨道上1.我会说为客户和书籍创建一些基本类,然后创建一个包含客户和书籍实例的CustomerBook关联类。然后,您可以让方法担心如何将数据加载到给定场景的列表中。
答案 2 :(得分:0)
我会将地址粘贴到Customer
,并有一个单独的书籍集。
Bookshelf
--Books[]
这样,Customer
没有,但可以拥有一本或多本与他相关的书籍。 PHP代码示例如下:
class BookshelfFactory {
public static function getBookshelf(Customer $customer) {
// perform some fetching here
return $bookshelf;
}
}
答案 3 :(得分:0)
从OOA&amp; D的角度来看,你有点倒退。在持久性(通常是关系数据库)层使用数据驱动设计是正常的。但是在OOA&amp; D中,考虑对象将发送和接收的消息更为正常(您为对象的方法而不是其成员建模)。我会这样思考:
Customer
+getBooks():List<Book>
+getAddress():Address
答案 4 :(得分:0)
我认为您的问题是实施数据映射层的问题。
您可以使用JOINS获得高性能的查询,这些查询会返回客户及其图书。
您的地图图层将其映射到相应的唯一对象,并负责为对象创建正确的1-many聚合。
此外,您可以满足浅层加载,显示属性可以节省不必要的数据量,只需要每个对象只需要一些属性即可传输。