岁月流转,往昔空明

C++博客 首页 新随笔 联系 聚合 管理
  118 Posts :: 3 Stories :: 413 Comments :: 0 Trackbacks
创建型模式的使用
GOF94的创建型模式,总共有五种。其中一种的范围是类的,四种是对象的。
1.Factory Method(virtual constructor)。
工厂方法在创建型模式里面的使用的频率是很高的,也是非常容易使用的。
由于工厂方法本身的一些特点,它们往往被说明成为静态的,如果这个静态函数就是待创建的类型的静态成员函数,那么,这就是Meyer所谓的 virtual constructor。(More Effective C++)这个东东很是厉害,我们可以利用它,依据数据创建正确的对象。
在游戏的过程中,存档和取档是在所难免的。在存储的过程中,你需要将一个自定义类串行化到文件中。这个到不是什么难事。但是如果你要从文件中读取对象呢? 首先你就需要知道这个对象的类,然后才能创建啊。这个时候,virtual constructor便可以显示出它的作用来。什么?你知道了?好,你写一 段代码给我看看。

TypeID id;//类标识,每个类唯一,可以籍此判断类型
switch (id)
{
case NPC_ID : 
//创建NPC,读入数据。。。
case MONSTOR: 

}

不不不,我绝对不是叫你要这么写!这段代码的代价太大了。有效率的做法是,我们使用一个映射表。方法不是静态的吗?那好,我就给它统一一个函数声明:
typedef (void*)(*PFnCreateObject)(ByteStream& stream/*资源流*/);
注意,这后面的这个void*理论上是需要返回一个指针,而这个指针又因为类型转换而失去了识别类型的作用。但是不要忘了,我们调用的是一个函数,一切需要弥补的缺陷,都可以在函数中完成。
因此,我们可以这样写一个查找表:
PFnCreateObject creatorFuncTable[MAX_TYPE_ID];
在程序需要读取存档的时候,我们可以:
void Load(ByteStream& stream)
{
  
//
  TypeID id;
  stream.Read(
&id);
  (
*creatorFuncTable[id])(stream);
  
//
}
这种做法的麻烦之处在于要为每一个类开一个ID。如果是手工完成这一项的话,是很需要点功夫的。而且维护起来也不是很方便。因此,这里可以用GUID再HASH的办法获取一个Hash表。保存对象时要保存相应的GUID,查找时使用Hash查找。
顺便说一下,如果有个非虚函数 Foo,有个类
class A
{
  
void foo() {
    
if(this == NULL) {
      
//操作,但是不能调用A类的非静态成员或虚函数
      cout << "Aha! 还是能运行哦!" << endl;
    } 
else {
      cout 
<< "没什么了不起的,地球人都知道!" << endl;
    }
  }
};
//
A* p = NULL;
p
->foo(); 

 这个调用是正确的!因为除了使用ECX传入NULL(this)以外,并没有非法的内存操作。因此,运行时也不会有错误。 当然,以上的调用实际上是不可取的。而且当foo为虚函数的时候,这种调用就不能正确进行了,因为虚函数是先要访问虚函数表的,而虚函数表又是对象而不是类的一部分,调用了就访问了错误的地址,所以其行为是不确定的。
所以说,Factory Method 的特点就是:依据不同条件,创造不同型别。(这里的条件就是烦人的类型ID)在创建之前,我们不能确定物体的型别。
如果我们将静态函数变为一个类(不是被创建的类)的成员函数,那么,这个结构就和Gof94上的描述一样了。Gof94上的 Factory Method,有着它自己的特点,这一点请参见书本。这里与Gof94的带继承的工厂方法相比,只是说对于不同的创建条件,构造函数的分 派方式不同而已。(这点我将在下面讲述到)
通过对工厂方法的使用,我们可以实现很多的功能,例如利用池分配等等。其中的一些功能,我们也可以通过重载operator new和 operator delete的办法实现,但是一些其它的功能,这种方法实现起来就会很吃力或者不可行,那么,工厂方法就为我们在创建的时候便搭建了一 个足够我们恣意施展才华的场所。
posted on 2007-06-07 17:45 空明流转 阅读(977) 评论(3)  编辑 收藏 引用

评论

# re: 乱弹游戏中的设计模式 - Factory Method 2007-06-07 21:46 李锦俊
I Like 设计模式~~
多写写类似的文章哦。
我还有好多个设计模式还没有理解啊。  回复  更多评论
  

# re: 乱弹游戏中的设计模式 - Factory Method 2007-06-07 22:19 pass86
估计PFnCreateObject creatorFuncTable[MAX_TYPE_ID];因该是
PFnCreateObject* creatorFuncTable[MAX_TYPE_ID];  回复  更多评论
  

# re: 乱弹游戏中的设计模式 - Factory Method 2007-06-07 23:25 空明流转
没有错,呵呵.  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理