1

(请记住,我是一个相对缺乏经验的程序员。我知道这个问题可以被视为过于开放,因为在 OOP 中有很多关于继承的哲学。这个问题更多地针对我的思考过程,即,我是否以经验丰富的程序员认为正确的方式处理这种情况?我的想法显然是准确还是不准确?)

我正在设计一个库存系统来跟踪有关 IT 硬件的信息,包括计算机、打印机、交换机、路由器、移动电话、硬盘驱动器和其他设备。我设计了一个数据库,现在正在规划一个前端应用程序。我打算让应用程序使用数据访问层、业务逻辑层和业务实体。我仍处于概念规划阶段,我意识到此时我不应该考虑实施细节,但我的思想倾向于向前推进。搜索功能的工作方式应该是:用户输入搜索条件并执行搜索。返回匹配设备(或唯一匹配设备)的列表。设备列表显示在某种类型的列表视图中,当设备被选中时会显示设备的详细信息视图。

我一直想知道在我的最终业务实体中使用继承是否会使我的应用程序受益,或者它是否会增加不必要的复杂性......或者它是否完全错误。我最初的想法是如图所示的设置:

(这不是实际设计,只是本文的简化概念)除了每个设备具有特定于类型的属性外,任何设备在任何给定时间都可以处于两种状态之一,活动或存档。我根本不知道如何建模。

概念类图

我开始考虑使用此设置时查询可能如何工作。从数据访问层查询设备的任何特定子类似乎很简单,例如

伪代码:

Computer comp = getComputerBySerialNumber(sn);
List<Router> routers = getRouters();

// I can then write code to display a list of basic device information and
// additionally display all details of a computer or router when requested.
// Obviously display would be handled in a different layer.

导致我写这个问题的问题是如何处理诸如“从特定位置获取所有设备”之类的查询。

// Returns a list of devices regardless of device type
// as long as they have the same location
List<Device> devsFromLocation = getDevicesByLocation(loc);

// List contains computers, routers, printers, etc.

如果我有基类对象引用,我将如何显示基本设备详细信息和特定设备详细信息?(尽量避免疯狂的投射或使用反射)。该位置的每个设备都将缺少其子类型的特定属性。如果我想显示有关特定设备的所有数据,我将不得不再次查询数据库以获取剩余字段。必须执行另一个查询是设计不佳的标志吗?此外,我将如何确定正确的设备类型?可能有一个大的 switch/case 语句测试每个Device.Type属性,执行正确的查询,返回完整的子类型并向用户显示详细信息?或者......返回包含完整子类型对象的单独列表然后遍历所有列表以在列表视图中显示公共属性然后在详细信息视图中轻松显示子类型详细信息是否更好?

这是一个有用的继承案例还是我滥用它?我目前正遭受信息过多的问题。我阅读了有关 OOD 的所有可能内容,并且我脑子里有很多规则和指导方针,我不知道我做的是否正确。我觉得我的大脑正在寻找应用我一直在吸收的信息,所以我在想象一个不正确的实现。我一直在考虑所有这些关于从编程到抽象的业务以保持代码的灵活性,但在某些时候你需要处理具体的类,对吧?从我的角度来看,继承是关于行为而不是属性。由于我实际上并没有对任何行为进行建模(或者我和我只是看不到它?)并且只是收集有关设备的数据,因此我很难解释它们的关系。由于这些类本质上是属性的愚蠢集合,我觉得它们都应该是单独的类。再说一次,我将在所有类中都有重复的字段,但在这种情况下真的很重要吗?

我知道有很多关于 OOD、继承、组合等方面的书。我读过其中的一些书;我目前正在阅读更多内容,并且我花了几天时间在线研究。每个人都方便地使用明显的继承示例。我正在做关于水果、动物和形状示例的噩梦。

感谢您花时间阅读我的问题,并感谢您提供的任何信息或见解。请随时提供任何其他提示、见解、商业秘密、埋藏宝藏地图、适合航海的船和六分仪,或任何您认为可能有帮助的东西。

4

1 回答 1

1

最直接的方法是向返回信息的基类添加一个信息方法,并让每个派生类型用正确的信息覆盖该方法。

这将允许您执行以下操作:

foreach (Base b in list)
  Write(b.Information());

如果您的输出需要更加动态,请考虑使用设备信息对象。

只浏览了你的帖子(所以我可能错过了一些使这成为一个坏主意的细节)我还建议你成为基类Active State的成员,因为'has-a(n)' (如果相同的话真的)。DeviceDeviceActive StateArchive State

除此之外,您的设计既漂亮又简单并且有意义。

编辑:

因此,您可能有一个Report想要写入信息的对象,因此您将拥有:

class Device{
  write_information_to_report(Report report);
}

这可以被派生类覆盖以添加派生的特定信息。

如果你真的想的话,你也可以抽象Report出来。InformationOutputter

这类事情的一个很好的例子是查看绘图形状:

class Graphics{
  line(int, int, int, int) = 0;
  curve(float, float, float, float) = 0;

class OpenGLDrawer : Graphics {
  line(int, int, int, int) { // Use open gl to draw a line };
  curve(int, int, int, int) { // Use open gl to draw a line };
}

class DirextXDrawer : Graphics {
  line(int, int, int, int) { // Use directX to draw a line };
  curve(int, int, int, int) { // Use directX to draw a line };
}

class Shape{
  draw(Graphics g) = 0;
}

class Triangle : Shape{
  draw(Graphics g) { g.line(... /* draw a triangle using line */ };
}

class Circle : Shape{
  draw(Graphics g) { g.arc(... /* draw a circle using arc */};
}

在这里你可以看到你可以让每个对象负责自己的功能,通用功能可以在基类级别共享,任何图形对象都可以绘制任何形状。

于 2012-07-04T10:02:40.977 回答