是否使用继承是恕我直言的成本/收益问题。
在实现继承时,通常会涉及额外的类、表、文档和其他在决定使用继承后需要创建的结果。
继承是关于特殊和一般情况的。首先,您可能想问一下案例之间的区别是什么——(称为鉴别器)。在您的情况下,它是预订类型,您可以通过对此类预订建模并根据预订类型实现不同的行为来避免继承。这将导致这样的设计:
避免继承
如果继承有很高的收益,因为每个特殊情况都有很多额外的属性、关系或操作,那么您可以应用它。
在这种情况下有
还有一些额外的字段
此时缺少的是使应用继承变得明智的常见行为。尽管如此,在下图中我还是添加了概括。目前不需要它,但只要有一般操作,您就想申请任何类型的预订:
应用继承
我绝对不会将集合建模为单例的子类。如果有的话,继承关系是相反的:
Reservation
是一种特殊的Regular Reservation
,其中startDate == endDate
和frequency == 1
.
但是为什么还要模拟两个类呢?考虑到所有的预订都是有规律的。从概念上讲,
Reservation
是只包含一个项目的集合。 Regular Reservation
是包含多个项目的集合。
继承不应该仅仅作为重用某些类成员的技巧。如果
RegularReservation
继承自 Reservation
,则意味着常规预订是某种简单的预订。真的是这样吗?例如 Date
的单个 Reservation
:有一个日期。定期预订有什么意义吗?
所以这里有一些瑕疵:
date
成员)的无用部分强加给所有类型的预订,即使它没有意义。这违反了接口隔离原则regular_reservation
成员)。所以如果明天你想创建一个MultipleReservation
(几个不相关的日期),你需要再次修改基类。这违反了开闭原则Reservation
的类需要了解不同类型预订的详细信息,以处理它们的特定能力。这违反了最少知识原则。 客房预订系统的挑战不仅在于登记预订,还在于了解每个给定时间段的房间是否空闲或是否已经有预订。
后果:
一个抽象的
Reservation
总是关于一个Client
预订一个Room
一个或几个TimeSlots
的价格。 TimeSlots
只是关于日期,时间,持续时间。这有助于确保关注点分离:
插槽的数量以及它们的创建方式将取决于
Reservation
的种类。但一般原则是删除预订会删除其所有时间段(好吧:如果过去有时间段怎么办?)。
你可能还有一些通用的方法:
getAllSlots()
将返回完整的时间段集合getSlotsInInterval(startDate, endDate)
将只返回间隔中的那些时间段