商业引擎的接口设计

         对于商业库来说最重要的就是代码的安全和接口的清晰了,换句话说,一个好的商业库
要提供给客户一个清晰的接口,让用户一目了然的同时,让用户无法看到具体的实现.
         为了达到以上的设计目的,我推荐Dll + 抽象类 为设计形式.
在这里我用一个商业物理引擎Novodex的接口结构作为示例来分析出它一些内部的设
计方法.它的接口形式非常类似于DirectX,只不过为了保证跨平台性,而没使用COM,但Dll +
抽象类的设计本身就合COM非常像,也可以说成是一种简化的COM.
        我先自己写一个基于Dll + 抽象类 形式的小库,了解了这库,再和Novodex提供的接口
(抽象类)作对比,就不难了解Novodex的核心结构的设计了.
       暴露给用户的接口所处的文件:MyObject.h , MyObject2.h , MyObject3.h ,.............
       库设计者对接口的实现:MyObjectImp.h , MyObject2Imp.h , MyObject3Imp.h , ...........
                                                MyObjectImp.cpp,MyObject2Imp.cpp,MyObject3Imp.cpp,........
       还有两个特殊的文件:CreateMyObject.cpp CreateMyObject.h
       其中:CreateMyObject.h文件中声明有一个dllexport的全局函数
:_declspec(dllexport)MyObject *CreateMyObject();用来返回一个MyObject接口指针,但实际上
内部用new操作符建立了一个MyObjectImp的对象,并把该对象的指针返回,这样我们的一切
就明朗了,在客户那里只需要得到接口(比如MyObject.h这样的文件),并且创建接口对象指针,
而不需要知道这些抽象类的具体实现(在MyObjectImp.X 文件中),然后用CreateMyObject返回
MyObjectImp这个实现类的指针,这样便能用接口指针操作接口内的一些成员函数了,这些成
员函数在接口中被定义为纯虚函数,所以当接口调用这些函数时,实际上是调用接口实现类
(MyObjectImp.X)中的成员函数.
         同样的,可以在MyObject.h中声明一个MyObject2 *CreateMyObject2()函数来创建另一
个接口,这点类似抽象工厂设计模式(Abtract Fartory),但这里的CreateMyObject2()函数就不用
声明为dllexport(为什么自己考虑吧,很简单的).
          就此完成了这个商业库的结构设计,扩展性也非常强,优点非常多.
下面是实例库的代码:
CreateMyObject.h:
#include "MyObject.h"
_declspec(dllexport)MyObject *CreateMyObject();
CreateMyObject.cpp:
#include "CreateMyObject.h"
#include "MyObjectImp.h"
_declspec(dllexport)MyObject *CreateMyObject()
{
MyObject *obj1 = new MyObjectImp();
return obj1;
}
MyObject.h:
#pragma once
//#include "MyObject2.h"
class MyObject2;
class MyObject
{
public:
MyObject(void);
virtual ~MyObject(void);
virtual void printHello() = 0;
virtual MyObject2 *createMyObject2() = 0;
};
MyObject2.h:
#pragma once
class MyObject2
{
public:
MyObject2(void);
virtual ~MyObject2(void);
virtual void printHello() = 0;
};
MyObject3.h:( 类似不写出来了)
MyObjectImp.h:
#pragma once
#include "myobject.h"
class MyObjectImp :
public MyObject
{
public:
MyObjectImp(void);
virtual ~MyObjectImp(void);
virtual void printHello();
virtual MyObject2 *createMyObject2();
};
MyObjectImp.cpp:
#include "myobjectimp.h"
#include "iostream"
#include "MyObject2Imp.h"
MyObjectImp::MyObjectImp(void)
{}
MyObjectImp::~MyObjectImp(void)
{}
void MyObjectImp::printHello()
{
std::cout<<"Hello World MyObject Version";
}
MyObject2 *MyObjectImp::createMyObject2()
{
MyObject2 *obj = new MyObject2Imp;
return obj;
}
MyObject2Imp.h:
#pragma once
#include "myobject2.h"
class MyObject2Imp :
public MyObject2
{
public:
MyObject2Imp(void);
virtual ~MyObject2Imp(void);
virtual void printHello();
};
MyObject2Imp.cpp:
#include "./myobject2imp.h"
#include "iostream"
MyObject2Imp::MyObject2Imp(void)
{}
MyObject2Imp::~MyObject2Imp(void)
{
}
void MyObject2Imp::printHello()
{
std::cout<<"Hello World MyObject2 Version";
}
客户使用测试:
#include "MyObject.h"
#include "MyObject2.h"
#include "CreateMyObject.h"
MyObject *obj;
MyObject2 *obj2;
int _tmain(int argc, _TCHAR* argv[])
{
obj = CreateMyObject();
obj->printHello();
obj2 = obj->createMyObject2();
obj2->printHello();
system("pause");
return 0;
}


         现在,来研究Novodex的设计结构,基于以上的知识,我们就算没有Novodex的源代码,但
依然能搞清Novodex到底是怎么设计接口的.
        Novodex最高层提供一个文件PhysiXLoder.h,其中有一个DLL导出函数:
NXPHYSXLOADERDLL_API NxPhysicsSDK *NxCreatePhysicsSDK(NxU32 sdkVersion,
NxUserAllocator* allocator = NULL, NxUserOutputStream* outputStream = NULL, const
NxPhysicsSDKDesc &desc = NxPhysicsSDKDesc());
用于创建一个NxPhysicsSDK 对象指针,哈哈,这里是不是和我的CreateMyObject很像?
很好,得到了NxPhysicsSDK对象后,通过NxPhysicsSdk接口我们可以看到他有一个成员函数:
virtual NxScene* createScene(const NxSceneDesc& sceneDesc) = 0;
用来创建一个NxScene指针,又和我的MyObject中的CreateMyObject2()很像对吧?
同样的NxScene又提供了一个函数:virtual NxActor* createActor(const
NxActorDescBase& desc) = 0;
又和我们MyObject2中CreateMyObject3()很像吧,呵呵,自此Novodex核心接口设计方式就搞
清楚了,它其它函数大同小异.
        这篇文章并没有研究引擎的具体代码,而是展示了一个通用商业引擎比较好的接口设
计方式,能隐蔽代码的同时提供最清晰的接口,希望能对大家有所帮助.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值