一个完整的面向对象分析与设计例子,与大家共同学习(转自呼伦贝尔博客)
第一部分 我需要最后实现什么样的功能?
首先说明,接下来 这部分内容,跟面向对象没什么关系,只是描述出我们接下来"需要做什么".
大家都知道电梯是怎么回事了,所以获取需求的过程我就不啰嗦了,直接把最后结果描述出来.(对于计算机专业学生或软件工程毕业设计的需求分析结果应该有些参考意义...起码可以看出怎么样的结果才真正有意义)
电梯楼层 1-10 楼(也就是没有什么地下室也没有中间跳过某些楼层,最普通的情况),一共有2部电梯.
如果一个在n楼(1<n<10)的乘客按了下行按钮,那么下一个正在向下走的电梯到了n楼必须停下接收乘客.
如果电梯里已经没有乘客了,电梯应该留在原位置直到再次投入使用.
在将乘客送到目的地以前电梯不允许反向运动.(也就是电梯比如把乘客从9楼带到楼下,如果在走到4楼的时候5楼有人要下,电梯不能从4楼回5楼去,而要把乘客带到楼下再回来)
满载的电梯不再收人.
电梯里有个按钮面版,里面有10个楼层的按钮. 按下按钮表示该楼层变成一个目的地,按钮会发光,到达以后按钮不再发光.
建筑物2-9楼层有一个按钮面版,上面两个按钮分别是向上和向下.1楼只有向上,10楼只有向下.
电梯有一个控制中心来自动控制,不用人手干预.
............(其他,略)
第二部分 到底上面的需求描述中,哪些东西可以成为我需要来 "面向"的"对象"?
首先,我们要选择出候选的对象,然后再在候选对象里选择真正为程序设计所使用的对象.
候选对象的选择有很多方式,比方说"名词短语频率分析",对上面那段去分析看哪些名词出现次数很多,说明可能比较重要,可以直接拿来当候选对象. 比如楼层,电梯,按钮,乘客,都出现很多次. 当然还有另外的方式,比如"按方面建立" (PS: I'm sorry,我是个实用主义者,只要目的达到了...我不喜欢像一些书本上那样用些概念糊弄人,上面红字的两个方法的名称是我临时取的....也许不好听,也许他们有更优美的名字....反正这不是我们该担心的,留给教材编写人员取操心吧...) 从 人\组织\设备\物品\业务\事件\表格 几个方面去找对象去.
这里要注意的是对象的选择要看具体情况的,比如 ... 我们把 "放飞希望" 作为一个具体的对象实例 ( ^_^ ), 如果在医疗系统中,可以抽象成 "人" 这个类,由 脑袋\身体\手\脚.....等部分. 如果是在教育管理系统中, 就不能这么处理,可能要抽象成 "老师" 这个类, 包括 教学年限\工资\所教科目\.... 等内容.
还有一点需要注意的是不要跨过系统边界. 系统之外的事情就不要管了,就说我们这个电梯调度, 电梯的生产日期啊什么的,还有乘客的姓名, 都根本雨系统无关,这些是不需要的.
最后有一点被非常非常非常非常非常多的工程师们所忽视的就是建立面向对象分析模型的时候, 只应该考虑逻辑,而不要去考虑跟实现技术相关的东西. 比如按钮是塑料的还是金属的, (当然这个很明显是分外的事,大多数人在做调度分析的时候不会考虑这个,不过有些情况却很隐蔽..)
现在回到我们具体问题,假设现在我们列出来的初步的清单是这样的(可能100个人有100个列法,不过没关系,这是正常的...): 电梯\电梯门\电梯位置\乘客\目的地按钮\大楼....
这离真正可以用的对象还差很多, 我们需要对每个词进行分析,看看到底是不是,值得不值得把这个当一个对象来考虑.我们分析从以下几个方面看:
它在系统里有功能吗? (比如电梯天花板 就该删除掉...如果有的话...)
其他对象需要这个对象帮忙做点什么事吗? (比如乘客需要电梯把他带上去...)
其他对象需要这个对象的数据吗?(比如控制中心明显需要知道电梯现在在哪..)
这个对象是不是包含了有用却不对别的对象公开的内容.(比如电梯上面的吊链和发动机明显是有用的,不然电梯无法动也就无法调度了, 但是明显对于其他对象,都是不需要公开的, 不管是乘客还是控制中心都不需要控制电梯的马达---这里可能有人要有意见了, 控制中心不控制电梯马达么? 答案是不该控制,控制中心应该只告诉电梯你要向上还是向下还是停, 至于马达转多快怎么转,是电梯自己的电路来控制的才对, 责任分开明确有利于系统的维护.)
这个对象有没有一个生存期,是不是描述了 产生--各种运行状态--消亡 的信息.比如一次电梯召唤-(谁想个好听点的名字? 呵呵...) 产生是用户按了向上或向下的按钮. 然后进入 "电梯来" 这个状态, 再进入电梯停(包括开门,乘客进去,关门)的状态,然后又是 "电梯走" 的状态,再之后是电梯再停给用户下去,然后这个电梯召唤以电梯停止移动等待下次召唤作为结束.
如果向应用领域的专家(这里比如是电梯工程师)描述这个对象,他是否可以马上明白重要性? (比如如果你对一个电梯工程师说 "调度工厂",他应该就不明白..因为工厂模式是面向对象设计的手段,跟电梯这个主题本身没多少联系)
以上列出的6点,不一定要每点都符合,不过如果每点都不符合,那不用考虑...删掉吧......
然后考虑系统以外的情况了. 这些对象中:
系统能识别吗? (比如对于超重还是不超重...有些就可以识别,有些电梯就不能..)
哪些是系统必须做出响应的(用户按的按钮明显就是一个...)
对于发生的事件(比如按下按钮,比如电梯门打开) 哪些对象可以识别它?
有没有没用上的?
还需要其他对象吗?
有没有不能识别又不需要响应的对象(比如用户的帽子?? ^_^) ,不过要注意,并不是绝对的,在极少数情况下,不能识别又不需要响应的对象是有用的.不过那是后话了,先不考虑它...
系统需要跟其他系统相连么? (比如,跟火灾警报系统相连, 火灾发生时不准打开电梯门...这里当然我们不考虑这么复杂,但是毕竟是存在这样的东西)
用于沟通两个对象的对象是不是不小心漏掉了? (这是常见的)
在你删除一个候选对象的时候,问问: 去掉以后系统会怎样? 如果我要重用一个包含了这个对象的一大块功能,这个对象到底会给真的用上么?(注意重用是非常重要的,绝对不要为了一个地方而写程序,程序要可以在不同地方重用,就像不会有生产一个电视机的电视机厂一样)
不断重复上面的过程,最终,你应该从不断增加新东西和不断删除东西后获得一个有些用的列表,假设如下面这样:
到达事件: (就是表示电梯到了,包括开门,进电梯,关门..还有灯亮灯灭等一系列内容..)
到达按钮面版(就是电梯里那10个按钮)
电梯(这个没什么疑问了......)
楼层
........................(其他略)
然后要做的事情是给每个词一个文字描述,比如 电梯的描述 如下
Elevator (类名一般请不要用中文....虽然你要用中文也行...):执行电梯的控制(上走,下走)和报告功能(告诉控制中心现在自己在几楼..), 内部封装(就是不对外公开它是怎么做的,只公开结果)了 控制电梯运行(马达怎么转..), 报告电梯位置,识别电梯是否准备就绪的各种服务. 他包括的属性是电梯的 运动方向\位置\状态 方面的信息.
最后出来的对象不可能证明就是对的,也一般不会全错, ^_^ 人的问题....注意最终用户也许会对这个有影响,所以最好还要问问他们,如果他们提出些比较麻烦的意见,如某种特定实现技术(比如如果电梯这个楼是一家生产音响的,也许老总有想法就要在电梯里有个音箱,电梯每到一层楼会报一次位置......-_- ....) 应该用专业角度劝他不要这样,如果他一定要.......那你也没办法了,谁让他是出钱的... ^_^
这个模型可能会在后面被修改很多,做好心里准备.
最后说一下命名, 对象的类名 应该是个类而不是个功能.或一个属性. 比如 可以叫"电梯" 却不好叫 "电梯颜色"或 "电梯上升". 对象类名最好全部都惟一,实在不好惟一了,就用不同的包分开,就像把相同文件名的不同文件放不同的文件夹里就行. 对象名称必须在应用领域有意义(也就是在这里必须在电梯界有意义, 而不能只在软件界有意义..) 用 名词或 形容词+名词, 不要用 名词+动词 的方式. 不要出现 "和","或","与"之类的内容.(比如人就叫 Humen 不要叫 LadiesAndGentalmen... ^_^ )
现在,大家列出些什么对象了呢?
ArrivalEvent
ArrivalPanel
DestinationEvent
DestinationPanel
Elevator
ElevatorMotor
Floor
OverweightSensor
SummonsEvent
SummonsPanel
..........................................
大概是这样的一些东西,(可能跟我这个差十万八千里,不过没关系,那也是正常的....如果照上面说的做了,那应该也错不到哪去..)
好了,....今天先到这,未完待续
抛砖引玉, 思考面向对象是什么? (面向对象系列之二)

