第4章
一个标准的面向对象解决方案
概述
本章对我们在第3章讨论的问题,“一个迫切需要灵活代码的问题”,给出一个初步的解决方案。这是一个合理的初步尝试,它能够迅速地解决问题。不过它却漏掉了一个重要的系统需求:CAD/CAM系统持续演化时所需要的灵活性。
在本章,我基于面向对象描述了一个解决方案。它并不大,但确实能起作用。
注意:在本章的主体部分,我将仅展示Java代码示例。对应的C++代码示例在本章的末尾。
用特殊手段来解决问题
考虑第3章“一个迫切需要灵活代码的问题”里描述的那两个不同的CAD/CAM系统。我该怎样构建一个信息析取系统,才能使得不管使用哪一个CAD/CAM系统,对客户对象而言它看起来都是一样的呢?
通过思考如何解决这个问题,我推断如果我能解决槽的问题,那么我也能用同样的方案来处理剪切块、洞等特性的问题。通过对槽的思考,我发现我能够轻易地特化每一种情况。也就是说,我将有一个Slot类。在面对V1系统时,我将为它生成一个派生类,在面对V2系统时,我将为它生成另一个派生类。如图4-1所示。
图4-1 槽的设计
通过对每一个特性类型进行扩展,我就完成了这个解决方案,如图4-2所示。
图4-2信息析取问题的原始解决方案
当然,图4-2展示的是相当高层的设计。每个V1xxx类将会和相应的V1库通信,而每个V2xxx类则会和V2模型中的相应对象通信。
如果单独地来看每一个类,这个解决方案就更加容易想象了。
l V1Slot可通过记住它所从属的模型以及被实例化时它在V1系统中的ID来实现。这样,任何时候当V1Slot的一个方法被调用以获取信息时,这个方法将不得不调用V1中的一序列子例程从而得到相关的信息。
l V2Slot将会以一种更加简单的方式被实现,即每个V2Slot对象将会包含V2系统中的一个相应的槽对象。这样,任何时候当该对象被查询某种信息时,它将简单地将这个请求传送给OOGSlot对象并将响应回送到先前发出请求的那个客户对象。
图4-3展示了一张包含V1和V2系统的更为详细的图。
图4-3 初始方案
我将为这个设计中的两个类提供代码示例。这些示例仅仅用于帮助你理解如何实现这个设计。如果你觉得你能够实现这个设计,请随意略过下面的Java代码示例(C++代码示例在本章的末尾)。
示例 4-1 Java代码片段:
实例化V1特性
// 实例化特性的代码片断
// 不提供错误检验——仅用作演示
// 每一个特性对象需要知道和它对应的模型号码以及特性ID
// 以便在收到请求时获取信息
// 注意这样的信息是如何传送进每个对象的构造函数的
// 打开模型
modelNum = V1OpenModel(modelName);
nElements = V1GetNumberofElements(modelNum);
Feature features[] = new Feature[MAXFEATURES];
// 为模型中的每一个特性做
for(i= 0; i < nElements; i++) {
// 确定当前的特性并创建适当的特性对象
switch(V1GetType(modelNum, i)) {
case SLOT:
features[i] = new V1Slot(modelNum,
VlGetID(modelNum, i));
break;
case HOLE:
features[i] = new VlHole(modelNum,
VlGetID(modelNum, i));
break;
}
}
示例 4-2 Java代码片断:
V1方法的实现
// modelNum和myID是私有成员
// 它们包含对应模型和特性(在V1中的)的有关信息
class V1Slot {
double getx () {
// 为V1调用适当的方法以得到所需要的信息。注意:
// 为得到信息,这个方法实际上可能调用V1中的几个方法
return V1GetXforSlot(modelNum, myID);
}
}
class VlHole {
double getx () {
// 为V1调用适当的方法以得到所需要的信息。注意:
// 为得到信息,这个方法实际上可能调用V1中的几个方法
return V1GetXforHole(modelNum, myID);
}
}
示例 4-3 Java代码片段:
初始化V2特性
// 实例化特性的代码片断
// 不提供错误检验——仅用作演示
// 每一个特性对象需要知道它在V2中对应的特性
// 以便在收到请求时获取信息
// 注意这样的信息是如何传送进每个对象的构造函数的
// 打开模型
myModel = V2OpenModel(modelName);
nElements = myModel.getNumElements();
Feature features[] = new Feature[MAXFEATURES];
(待续)
示例 4-3 Java代码片段:[1]
初始化V2特性(继续)
OOGFeature *oogF;
// 为模型中的每一个特性做
for (i= 0; i < nElements; i++) {
// 确定当前的特性并创建适当的特性对象
oogF = myModel->getElement(i);
switch(oogF->myType()){
case SLOT:
features[i] = new V2Slot(oogF);
break;
case HOLE:
features[i] = new V2Hole(oogF);
break;
}
}
示例4-4 Java代码片段:
V2方法的实现
// oogF是V2中对应的特性对象
class V2Slot {
double getX (} {
// 调用oogF的适当方法以得到所需的信息。
return oogF->getX();
}
}
class V2Hole {
double getX () {
// 调用oogF的适当方法以得到所需的信息。
return oogF->getX();