CAD软件日益庞大,现有的大中型的CAD系统都有一定的历史,陈旧代码比较多。随着硬件设备的不断提升,操作系统的更新和用户不断提出的新需求,代码的重构和新特性的添加变得越来越困难。那么,如果在CAD开发的初始阶段,就使用适当的设计模式,立足于良好的架构,那么这个系统就会对变化更加敏捷,从而提高市场占有份额。

AutoCAD是一款市场占有率很高的软件,我觉得他成功的很大的一个因素是用户友好,不断改进交互界面。而这个要有良好的架构设计支持。对于CAD软件来说,架构设计至关重要。我见过的架构有:

  • 基于COM,所有的功能由COM组件封装起来。好处很多,但是在现在的操作系统下,尤其是跨平台的需求,就显得过时了。
  • 模块化。纵向,横向切分系统模块。使用小的内核模块,不断添加新模块。这个思路主要是指二进制模块,也就是dll为核心。好处显而易见,AutoCAD就是代表,很多软件都在想这个思路走。
  • Web。这个是下一代的产品,还不是很成熟。

模块化,有时候也可以在源代码级
实现。就是说一个或者几个文件,定义一些功能类,实现一个模块。这些源代码文件可以组织在不同的dll中,适合不同的需求。坏处就是需要更加繁琐的文档。这种设计适合软件核心的开发,达到最大的灵活性。我们也可以看到这个趋势。Windows7
开始,微软开始把内核的好多函数分成不同的,小的dll来实现,这样的话,很小的模块的变化,不会影响内核的震动。所以,源代码级别的模块重用设计,很适合核心代码的设计。而外围扩展模块,就可以在这些核心模块的基础上,进行扩展和开发。这个也是一个可以形成生态链的基础。

面向对象的设计思想很强大,但是在具体应用的时候,很容易陷入僵局。部分原因就是设计思路,具体地说,在设计时,将问题表达为类和对象的平行的体系,这样就很难扩展和维护,如果增加新的需求,架构就会不稳定。这种设计的缺点就是不能将易变的对象和系统的其它部分分离,使得
系统的架构修改变得困难。

对于CAD软件来说,相对不变的是很多几何算法。由于数据定义相对稳定,这样的话,可以抽象出接口供其它部分使用。但是用户界面(GUI),文件读写(I/O)等都是容易改变的部分。ANSI/SPARC
设计范式就是一个很好的解决这个问题的思路。可以参看:

D. Tsichritzis, A. Klug (eds) “The ANSI/X3/SPARC DBMS framework: report
of the study group on database management systems”, Information Systems,
Volume 3 (173-191), Pergamon Press Oxford UK 1978.

这种范式,将问题分解为三个层次,核心层(物理层),概念层,表示层。核心层负责处理物理数据格式,概念层相当于逻辑层,封装算法和逻辑,将底层的数据提供给表示层。表示层为用户服务。在设计架构时,可以使用这三个层次来思考和设计。

ANSI-SPARC_three_level_architecture

这里针对在CAD软件设计中常用的三个设计模式来说说看怎么应用三层设计范式。这三个设计模式是:Visitor,
Bridge,
Composite。Visitor和Bridge这两个模式在表现层中使用,可以提供不同的灵活的界面设计,封装底层的数据给用户呈现不同的显示。Composite则可以在三个层中使用。下面分别来说说这三种设计模式:

Visitor

这个设计模式主要是为了分离类的核心功能和附加功能。所谓核心功能,就是设计这个类所需要的不变得功能,而附加功能则可能在不同条件下需要有不同的实现。这里可以用一个Circle类的例子来说明。对于Circle来说,最核心的功能有:

  • 构造Circle
  • 获取circle的几何属性
  • 和其它几何题之间的关系计算

除了这些属性,其它的部分都可以变化,就需要算作是附加功能,可以用Visitor模式进行分离实现。在表现层,我们需要不同的显示方法,那么这么设计就不合理了:

1
2
3
4
class Circle
{
void Draw ();
}

如果这么设计,当我们在其它环境下使用时,需要重新实现这个Draw函数之后才能使用这个类中的几何功能了。当然从开发的角度来说,这个Draw的代码总是要写的,但是,设计模式的目的是为了让你的类库保持稳定,能够重用,最小修改才能最少的引入错误。针对这个例子,我们可以引入新的类:

1
2
3
4
class Shape
{
void Draw (Circle& circle);
}

这样的话,这个Draw附加功能就可以在另外的类中实现,得到最大的灵活性。

现实中,我们可以看ObjectARX,他有几何库,其中没有绘制等其他的附加功能。而数据库类则增加了绘制,格式读取保存等功能。当然,这个设计未必是严格的按照这个模式来。但是,我们可以看到这么设计的好处

Visitor模式的其它用途可以参看四人帮的那本书。这里介绍的是在CAD软件开发中的用途。

Bridge模式

这个模式主要是定义一个抽象的协议类。这个类可以看作是概念层的。而这个抽象类的实现,则位于表现层。定义在概念层的类规定了类的行为,与其他对象的交互规则。在表现层,用户可以实现不同的外观。其实这个模式经常和template
method模式混合使用,在CAD开发中经常使用。

Composite模式

这个模式不仅在界面交互中使用,在底层数据结构设计中也有很广泛的应用。它的主要目的是为了简化接口,使得复杂的类型和简单的类型有同样的接口,同时能够支持嵌套的,递归的定义数据。

在底层数据数据中,经常可以见到这个模式。例如,基本的element类定义,可以是简单的几何图形,也可以是多个几何图形的组合,这种复杂的element同样适用统一的接口定义,简化了代码。

这三个设计模式只是在CAD开发中使用的模式中的一部分。还有很多设计模式可以帮助我们开发出更好的软件来。三层的设计范式可以帮助我们设计复杂的,可以扩展的软件。CAD开发商可以按照这个范式设计底层的数据读写核心,加上扩展的概念层类库,并且实现一个表现层的软件平台。第三方的开发者就可以在这个平台上,根据概念层和表现层提供的可扩展性,来开发用户自己的模块。在用户开发的模块中,由于核心的数据层已经被封装,这样的话,开发商和第三方开发者使用共同的底层数据模块,共享抽象的概念层协议,同时共存在一个表现层的软件平台中。这就为CAD开发商形成良好的软件生态链奠定了技术基础。这方面的一个典型的例子就是AutoCAD。