书上在讲这部分是没有提到设计模式,我之前一直犹豫是不是把这部分也做成笔记。看到后面关于模式的讲解,使我决定记下这部分内容,这将会有助于对后面即将到来的设计模式的理解。
这部分将说明传统面向对象中的一个典型问题——没有必要的继承层次结构,往往是紧耦合而且低内聚的。
一、问题描述:
- 从一个大型CAD/CAM数据库中提取信息,提供一个复杂而且昂贵的分析程序。
- 因为CAD/CAM系统还在继续发展,所以这个问题对代码的灵活性要求很高。
二、任务描述:
任务是编写软件工具从CAD/CAM系统中提取信息,然后又一个专家系统利用这些信息来控制零件制造流程。因为这个专家系统比较难于修改,而且生命周期比当前版本的CAD/CAM系统要长,所以想要编写的信息提取工具应该很容易适应CAD/CAM系统的新版本。
三、最初解决方案:
图1 解决方案高层视图
公司正在使用的是CAD/CAM系统的V1版本,新的V2版本和V1版本并不兼容。
在几何特征提取一层上多态性肯定需要,但在部件一层上不然。希望能够在CAD/CAM第三个版本推出时候,不希望对专家系统进行修改。
图2 解决方案的类图
专家系统通过Model类与CAD/CAM系统发生关系,Main类负责实例化Model类的正确版本。
接下来讨论CAD/CAM系统,非常糟糕的是,两个版本之间差别很大。
- V1版本本质上一个子例程库的集合,为了获取信息,必须进行一系列函数调用。(限于篇幅不详细描述)
- V2版构建的动机就是让其成为面向对象的,在V2中,系统请求模型是,将得代表模型的一个对象。这个模型对象包含部件的集合。部件类型与V1版本完全对应。
3.1 标准的面向对象解决方案
创建一个SlotFeature类,在使用V1系统是从该类派生一个类,在使用V2系统从该类派生另一个。然后推广到所有部件上,解决方案完成了!
图3 初步的解决方案
解决方案满足目标:
- 实现了通用的API。
- 从责任的角度定义了对象。(这一点很重要!后面笔记还会详细说明这一问题)
存在问题:
- 方法之间存在冗余——调用V1系统的那些方法有许多相似之处。例如Slot的V1getX方法和Hole的V1getX方法将非常相似。
- 杂乱——虽然主观性很强,但是这一因素值得考虑。
- 紧耦合——此方案存在紧耦合,这些部件之间关联着。如果出现以下情况,将可能要修改所有部件。
a)采用一个新的CAD/CAM系统
b)修改现有的CAD/CAM系统
- 弱内聚——内聚性非常弱,因为执行核心功能的方法分散在多个类中。
- 最最关心的是要为未来做准备,如果增加第三个CAD/CAM系统,将会产生部件数×系统数的类,这种方法很快会失去控制。
产生问题的原因:
这是分析人员常犯的一个错误,在开发的过程中过早的深入细节。这很自然,细节的解决方案比较容易,但是并非最好的入手点,细节问题处理应该尽量推后。
四、本部分小结
将一切作为特例来来解决问题非常容易,这种方式直截了当,但是这种方案有几个缺点:高冗余、低内聚和类爆炸。
过分依赖继承将带来超出正常维护的成本。