关于OOP的基本问题

时间:2010-02-19 15:35:36

标签: oop architecture

当我必须为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 / ??我希望有一个完美的解决方案

5 个答案:

答案 0 :(得分:3)

假设我理解正确,您的选项1接近良好。顾客和书是完全不同的两件事。您希望这些数据/功能分离,并且不应从任何公共基类(您已经创建)继承。

作为“Con”你说:我在我的UI之后构建了我的课程,并且有复制粘贴

  • A。如果您在确定设计和编写代码之前模拟了一些用户界面来帮助澄清要求,那就是,不错。
  • B。您的域对象的良好排列有助于消除复制/粘贴,而不是导致它。如果您在精心安排的类(通常是数据访问代码)中有一些看似重复的代码,这是典型的,请不要担心。您可以使用良好的数据访问层/工具,良好的共享日志记录资源等来解决。您的类中的重复代码只意味着您需要进行更多的设计改进,为所有人提供单独的类你的域名现实很糟糕。

在您需要处理客户和图书的页面上,您将使用客户对象和图书对象,可能还有图书集合对象。根据您的数据库/对象模型的设置方式,您可能正在处理其他对象以使客户获得他们购买的书籍。例如,客户可能同时购买一本或多本图书,这些图书与订单对象相关联,该对象引用了客户。所以,你可能会从

开始
  1. 客户
  2. 订单集合,其中包含所有客户订单
  3. 订购对象,并从那里到相应的
  4. 图书集合,其中包含所有
  5. 预订与该订单对象相关的对象。
  6. 这些都不需要相互继承。现在,让我们说让客户购买的所有书籍都是你做的很多,而你想简化它。然后,您希望直接从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聚合。

此外,您可以满足浅层加载,显示属性可以节省不必要的数据量,只需要每个对象只需要一些属性即可传输。