CROWD中文网
你的位置: Inflation Hedging Coin中文网 > CROWD中文网 >
rhapsody是我们正在使用的一个集建模与代码产生功能于一身的工具。它有一个很突出的特点,那就是支持很多os平台。噢,我的意思并不是说它像java一样,有着“write once, run anywhere”的本领,事实上,您可以在rhapsody中选择不同的目标平台,它将选择对应的编译器、连接器以输出您想要的二进制程序。 从代码层面来看,rhapsody提供了一组os抽象基类,也就是所谓的osal(os abstract layer),比如omosthread意味着一个线程、omosmessagequeue意味着一个消息队列、omosmutex意味着一个互斥量。rhapsody的应用程序框架正是通过操纵这些抽象基类的指针,达到与os交流的目的。 对于每个具体的目标平台,rhapsody需要从这组抽象类派生出一组具体类,并以相应平台上的api来实现基类中所声明的每一个接口。当然,如果rhapsody不支持您想要的os平台,而您的应用程序又偏偏想要运行于其上的话,很显然,编码的事情就得您来做。 或许您会同我一样,认为它真的是不过如此。可是,请听听这个响亮的声音: “是吗?年轻人,请保持冷静。”不用说,这就是andy! 看来另有玄机。我的目光立即开始在一个叫os.h的文件中搜索,因为所有的os抽象基类就定义在这里。忽然我发现其中竟然定义有一个叫omosfactory的类! “factory?什么嘛,学习操作系统时,老师怎没讲这个东西?”我开始自言自语。 “什么?连这个你都不知道啊……”andy探出头来,一脸的狐疑。 这分明是激将法,我知道他想尽快将我训练成oo杀手,可也用不着这么心急嘛。继续往下看,我发现omosfactory的定义如下: class omosfactory { public: static omosfactory* instance(); virtual omosmessagequeue* createomosmessagequeue(omboolean shouldgrow = true, const long messagequeuesize = omosthread::defaultmessagequeuesize) = 0; virtual omosthread* createomosthread(void tfunc(void *), void *param, const char* const threadname = null, const long stacksize = omosthread::defaultstacksize) = 0; virtual omosmutex* createomosmutex() = 0; // 其它成员函数的声明 ...... }; 原来是个名副其实的对象工厂呀,也就是说,将来所有的os对象都将通过它来创建!由于它是个抽象类,很显然它需要被派生,并由具体的派生类来完成真正的os对象创建工作。可是,我忽然隐约觉得有些不对。 “既然是个基类,为什么它没有声明一个为virtual的析构函数呢?”我嘀咕道。 “你怎么老是这么多的为什么,难道当初我就是看中了你提问题的能力?”andy总不忘给我些刺激。 “除非这个类的设计者确定不会有人企图透过一个pointer-to-base去删除一个derived object。” “既然如此,那你说说客户如何来使用这个类?”andy穷追不舍。 对啊,这可是个抽象类,这就是说不可为它定义任何对象。可是现在又竟然不能动态创建一个派生类对象,同时将其地址赋值给一个类型为omosfactory *的指针,这该怎么办呢? 突然,我发现了static omosfactory* instance();这么一句,马上想到去看看这个函数的定义。在文件vxos.cpp我找到了它: omosfactory* omosfactory::instance() { static vxosfactory thefactory; return &thefactory; } 同样,在文件ntos.cpp中同样有它: omosfactory* omosfactory::instance(){ static ntosfactory thefactory; return &thefactory; } 真相大白!不用说,vxosfactory和ntosfactory都是派生自omosfactory。事实上,针对vxworks的os类和工厂的定义及实现正是在vxos.h和vxos.cpp两个文件中;而针对win32平台的os类和工厂的定义及实现正是在ntos.h和ntos.cpp两个文件中。很显然,当客户写下 omosfactory::instance(); 时,他将获得一个类型为omosfactory *的指针,这个指针指向一个具体的派生类对象;而且,由于这个对象是被声明为static,这表明在程序生命期间,不管上面一句被写过多少次,只会有一个工厂对象被产生。无论何时,当客户想要获取一个互斥量时,他都只需这么写: omosfactory::instance()->createomosmutex(); 而不用管他的程序到底想运行于哪个os平台之上。 “真是个不错的idea啊!”我发出由衷的感叹。 “事实上,omosfactory实现了一个叫singleton的设计模式。”不知何时,andy竟然出现在我的身后,脸上似乎还带着一丝笑意,“当你保证某个类仅有一个实例,并提供一个访问它的全局访问点。你就可以使用这个模式。” “是的,您说的很对。不过我总觉得,多态的威力在这里真是发挥得淋漓尽致啊。” [[the no.1 picture.]] “其实这里还有一个被称作abstract factory的设计模式,或许这个能给你一些启示。”说着,andy不知从何处拿出一张小图片[1]: “你看,不管是os对象,还是创建这些对象的工厂,客户只需与它们的抽象基类打交道。而且,要正确运用这两种模式,客户还应该使用这些基类的指针。事实上,面对以上这这样一个singleton,除了这么做,你别无选择。”andy笑了笑,转身离去