免责声明:我没有正式学习过责任驱动设计,虽然我认为我教过的学生会证明我在课堂设计中讲了很多关于责任的内容。相反,这个答案借鉴了 25 年的面向对象设计经验,其中大部分是在 Java 中。
责任驱动与面向对象
在设计一个类时,我在很大程度上考虑了责任(所以我想我正在做你引用中定义的责任驱动设计)。理想情况下,我认为责任更多的是类的实例(或类本身)可以做什么,其次是它们存储的数据。这似乎与您的第二个定义一致。不过,在某些情况下,我无法坚持这个理想。
将数据的操作放在数据所在的类中(如您的第一个引用),我认为这是一个通用的面向对象原则(可能取决于您订阅的面向对象的学校)。通常表示将数据和代码放在一起。我真的不认为这是特定于责任驱动设计的东西(但当然也有它的位置)。
一个例子。假设一个Person
对象应该负责计算一个人的年龄。我会考虑这种健全的责任驱动设计。为此,Person
对象需要该人的出生日期。对我来说,面向对象的设计会将出生日期放在Person
对象中,这样我们就可以将代码和数据放在一起。这可能与例如保留出生日期列表相反。在我的理解中,将出生日期存储到单独的生日列表中的责任可能仍然是责任驱动的,但它不会是面向对象的。这意味着,我真的不同意你的第一个定义。
所以我理解你的困惑。我同意你的观点,这两个定义并没有说同样的话。
不过,我正在创造一个在现实生活中并不那么清楚的区别。在我的日常工作中,面向对象和责任驱动的设计很好地结合在一起,我不会有意识地思考差异。
另一个引用 - 关于面向对象
封装是一种将数据(实例变量)和作用于数据(方法)的代码包装在一起作为一个单一单元(如类)的机制。
来自OOP:关于面向对象编程你需要知道的一切,其中封装被认为是 4 个面向对象编程概念中的第一个。
Java 标准库中的 RDD 示例
我认为文档中的以下引用表达了这些接口和类设计背后的非常清晰的责任驱动思想:
- 为了允许序列化不可序列化类的子类型,子类型可以负责保存和恢复超类型的公共、受保护和(如果可访问)包字段的状态。仅当它扩展的类具有可访问的无参数构造函数来初始化类的状态时,子类型才可以承担此责任。(
Serializable
)
- 在实践中,按钮的 UI 负责调用其模型上的方法来管理状态,如下所述: (
ButtonModel
)
- PersistenceDelegate 类负责根据类的公共 API 中的方法来表达给定类的实例的状态。例如,通过
readObject
和writeObject
使用的方法将持久性的责任与类本身相关联,而不是ObjectOutputStream
像使用此委托模型的流这样的流XMLEncoder
可以使其行为独立于类本身进行控制。( PersistenceDelegate
)