对象设计:角色、责任和协作
书名:对象设计:角色、责任和协作
英文名:
Object Design:Roles,Responsibilities,and Collaborations
作者:
[
美
]Rebecca Wirfs-Brock, Alan McKean
出版社:人民邮电出版社
阅读类别:精读
2007
年
3
月
18
日星期日
这是一本由
RDD
(责任驱动设计)的创始人写的关于
RDD
的书。从
Larman
的《
UML
和模式应用》中知道了按角色、责任和协作来设计对象,而基于这种思想进行设计我从看到这本书之前就已经这样做了,我把它看作是一种自然的方式,对象就像人一样,可以一起来完成一些事情,那些现实世界中的非生命体就像卡通人物一样,在对象的世界都具有了生命。我当时在那本有一章关于面向对象介绍的书中说过“这里面有一个朴素的思想叫做换位思考,把你想象成你要设计的对象”,看看它该做点什么。
这本书从一个理论的高度概括了我自悟的那个设计对象的自然方式,同时给出了不同情况下的应用,并加入了设计模式。
下面是一句金子般的话,是
RDD
的核心思想。我是超级赞同这句话,并且觉得那些一味考察算法和数据结构还号称自己使用面向对象构建系统的公司去死吧!
对象不仅仅只是简单的逻辑和数据的绑定,它们是对象世界中享有各自责任的一员。
第一章
设计概念
对象机器
将一个软件系统,看成是一部对象机器,而且是一部非常复杂的机器(比我们认识的机器还要复杂)。为了管理这种复杂性,我们将系统行为指派到具体特定角色的对象中(
P3
)。
作者接着为我们补充了对象设计的补充概念(之所以叫补充,或许在
RDD
之前不会考虑这些,嗯,也许之前的人们总是在关注算法和数据结构之类的东西,就像今天许多公司一样。):
应用系统
=
一组相互作用的对象
对象
=
一个或多个角色的实现
角色
=
一组相关的责任
协作
=
执行一项任务或掌握某种信息的义务
契约
=
描述协作提纲的一种协定。
不知道是翻译问题还是我理解能力有问题,总觉得这些话说得有些别扭。看看下面作者的详细解释吧。
角色、责任和协作
角色与责任的关系
P3
为了生存,对象将具有特定的使命——在给定环境中扮演一种角色。扮演相同角色的对象可以相互替换。
这个角色的概念应该就是生活中角色的本义吧,比如作者所举的快递公司的例子,它们都扮演快递公司的角色,快递公司就是所说的对象,按照绿框中的文字来讲,角色就是责任,然而我觉得这句话应该是说:角色具有责任,因为其具有这种责任,则被称为这种角色,好比,具有给学生讲课这种责任的就叫老师角色,然后李老师、张老师这些对象都扮演老师这样的角色,它们都具有给学生讲课这种责任,
这本书的一个巨大的特点就是:每句话都很有用!
责任
就是对象在系统中要做的事,担当的使命,完成的工作。相互替换使用
指的是扮演相同角色的对象可以相互替换,所以我觉得可能是翻译的有些问题。
因此我觉得这句话的完整理解应该是:
角色具有可以由不同对象承担的责任。
对象与角色的关系
P3
考察一个对象时,最好先思考一下对象到底扮演什么角色?
P3
在软件机器中,角色就是一个插槽,在运行的时候由对象来填补。
我觉得这似乎就是在说:设计软件系统时,先考虑角色,一个系统,应该由什么角色来组成——比如学校中,有教师、行政主管、后勤等角色组成,而至于由谁来扮演这些角色,等到学校运转起来再定。
说某个对象扮演某个角色,是因为它担当了这个角色的责任。
然而我还是有些疑惑,在一个软件系统中,由多个对象扮演一个角色,是怎样一种情况呢?多态?
对象社区
P5
软件是由一组共同工作的对象所组成的社区。它们之间通过请求和应答相互协作。每个对象都由各自的责任,都为社区提供自己的信息和服务。
这里面说出了对象软件的本质是对象社区。我是很赞同这种说法的,我们可以通过一种自然的思考方式,来考虑对象设计,对象应该具有什么责任(掌握什么信息,提供什么服务),以及对象是如何协作完成大型任务的。
P5
若对象能够在自己所持有的信息基础之上展开工作,那么它就具有更高的智能度。
这就是
Larman
所谓的“信息专家模式”,由掌握信息的对象来完成基于该信息的任务。知道一个对象所持有的信息似乎比了解一个对象的责任更容易,至少从我的实践中可以得到这样的结论。
对象
Role Stereotypes
这本书将
Role Stereotypes
翻译成角色构造型,意思指代对象的本质和角色的类型。采用构造型这个术语应该是为了简单,不过我觉得它不能很好的表明它的意思。所以我还是觉得就叫角色类型就好了,并且我认为对象的角色类型就决定了它的本质是什么。
角色类型
:
l
信息持有者:掌握并提供信息。(只扮演这一角色的应该就是
VO
了)
l
构造者:维护对象之间的关系以及与这些关系相关的信息。(指的应该是关联对象)
l
服务提供者:执行工作,通常为其他对象提供服务。
l
协调者:通过向其他对象委托任务来响应事件。
l
控制者:进行决策并知道其他对象的行为。
l
接口:连接系统的各个部分,并在它们之间进行信息和请求的转换。(这里的接口应该就是接口的本意,就是个连接器,而不是面向对象语言中的接口——只有方法声明的类)
就像一个人可以扮演多种角色一样,一个对象也可以同时属于多种角色类型。比如一个完整的对象基本上都是信息的持有者和服务的提供者。角色类型只是将角色按不同责任分类,具有一定的指导意义,但不必太苛求。以自然的态度对待就好了。
对象契约
对象契约就是对象的使用说明书,在什么条件满足的情况下才能使用这个对象(前置条件,在这个书里叫使用条件),使用了这个对象会产生什么作用,这个对象是干什么的(也就是后置条件,本书叫使用效果)
对象契约描述了一些条件。在这些条件下,对象能确保其正确工作,并产生合理的效果。
领域对象
P8
领域对象为开发者与用户一起讨论系统提供了一个公共背景。它代表的是用户和特定领域专家熟悉的概念。
P8
领域由用户所需的信息、服务以及联系两者的结构所组成。
接口
P10
接口表达了对外提供服务并且解释了该如何得到这些服务。
接口就是两个对象名片。我忽然觉得接口的概念和
OOP
中的接口是统一的,大家都是提供给外部系统其可以被外部系统使用的服务。
我们把一个对象的设计分成
3
个部分:它的公开接口、使用条件与术语及实现其业务的私有细节。
类
在这一部分中,作者给出了很多好的关于软件类的观点,这有别于来自于
C++
阵营或数学领域的专家给出的观点,那些观点大多数都是将类看成数据类型,也有别于那些没什么编程经验的对象专家,将类简单类别成生活中的类。
作者认为:我们赋予一个类的特性就是那些我们期望它的实体会拥有的特性。我们赋予一个类实体的任何关于“知”、“行”或者“决策”的责任都会在类定义中具体化,并且被类所包含的实体方法来实现。
类通常拥有两种角色:首先,它们就像一个工厂,初始化对象并且实现它们自身的责任;其次,它们就像一个独立的服务提供者,为与其有关联的客户提供服务。
尽管共享一个定义,但实体之间通常都会表现出不同的行为。因为它们所依赖的自身私有数据和关联帮助对象都是不同的。
共享一个定义就是说,这些实体都是由一个类创建的,类就是这些实体的定义。在这里,实体就是实例。
虽说将文中框图中的内容摘录出来是因为它们都很精辟,然而仔细阅读本书的每一句都将非常有收获,作者细致清晰毫不含糊的讲解,使人感觉犹如醍醐灌顶。这是我看过的关于对象和类的关系最精辟的讲解!
P14
一个对象数据域内的变量值就标识着该
对象的状态
。这些变量定义了一个对象的内部结构以及其看待关联对象的方式。一个对象可以持有其他对象的引用,
这些引用使得一个对象可以看见其他对象并且与其相互作用
。这些
引用
并没有说明对象之间是如何交互的,只不过表明了对象之间潜在的协作关系。
复合与继承
在一个对象组织模型中,对象之间通常存在两种关系:复合和继承。
家族关系树刻画了一群人之间的关系结构。向这个关系树中添加新成员只会有两种方式,要么是婚姻迎娶
(
复合,在生命周期中有效,并且可以废除关系
)
,要么就是作为某成员的新子孙
(继承,一旦产生了就改变不了了,因为你爹永远都是你爹!)。
复合就是在一个对象内部调用其它对象的服务来完成任务。复合就是我们最常用的一种扩展对象功能的方法,或者是说对象协作的方式。
一个对象通过协作来调用另外一个对象的责任
(复合)。同时,一个对象通过继承拥有另外一个对象所拥有的责任。
体系结构风格
设计模式
是一种在协作者之间分配责任的风格,目的是为了解决特定的设计问题。
体系风格
是软件对象的组织风格。常见的体系风格有:层次式(
layered
),管道—过滤器式(
pipes-and filters
),黑板式(
blackboard
)