MFC中的设计模式之厂(Factory)

本文探讨了MFC中对象动态创建的原理,通过分析CRuntimeClass::CreateObject()方法,揭示了如何利用宏和链表实现一个函数创建多种对象的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  厂(Factory)顾名思义,就是制造东西的东西。具体到软件开发上就是指用来生成对象的“东西”。这里的“东西”可能是一个方法(例如全局函数),也可以是一个类(COM中的类厂)。简单来说,运用厂的目的是隐藏对象具体的创建过程,客户代码提供创建对象所需要的材料,然后就从厂那里拿到已经创建好的对象,而不用关心对象是怎样创建的。厂的思想虽然简单,简单的几乎使我们忽视了它的存在,但是它却频繁的出现在代码中,成为使用最频繁的设计思想。

最简单的厂就是一个函数,这个函数只创建一种对象。例如以下的代码:

class Football;
Football* CreateFootball();

从函数名CreateFootball就可以看出,这个函数用来创建一个Football对象。当然可以给函数添加一些参数用来指定创建的对象的属性。这个函数(或者说类似的函数)有个致命的问题,就是功能过于单一和死板,如果我们有N种对象,就需要写N个相应的函数来创建他们。

MFC仅用一个方法就可以创建所有从CObject派生的对象。这个方法就是CRuntimeClass::CreateObject()。

构造对象的时候,首先要知道对象占用多少内存空间,还需要一个构造函数去初始化构造的对象。在CRuntimeClass中正好有两个成员变量涉及到这两个方面的内容:
m_nObjectSize - The size of the object, in bytes
根据它的值,创建对象的时候就知道分配到少的空间
m_pfnCreateObject - A function pointer to the default constructor that creates an object of your class
这是一个指向对象默认构造函数的函数指针,通过它在创建对象的时候可以调用默认的构造函数初始化对象

将CRuntimeClass和我所要创建的对象联系起来,即让CRuntimeClass知道要创建的是什么东西。这里MFC是通过两个宏(DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE)来建立这个联系的。通过这两个宏,任何从CObject派生的类都会有一个相应的CRuntimeClass对象,这个CRuntimeClass对象储存了要创建的对象的一些信息,比如上面提到的对象的大小,构造函数指针等等。

MFC使用DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏来实现RTTI。简单的说,每一个类相应的CRuntimeClass对象(静态对象)会被添加到一个静态的,全局的CRuntimeClass类型的链表上,以后通过查找这个链表,就可以找到每个类对象的CRuntimeClass对象。

对于CRuntimeClass::CreateObject(),其实也是每一个对象对应一个厂函数,只不过是不需要手工的添加这些厂函数,MFC用更巧妙的方式实现了。CRuntimeClass还提供了一个静态函数:static CObject* PASCAL CreateObject(LPCSTR lpszClassName),这个函数仅仅需要类名就可以创建相应的对象,真正做到了一个函数创建N种对象.

通过对MFC中对象动态创建的分析,如果想让一个函数可以创建多种对象的能力,函数原型一般具有以下的特征:

1。函数返回值。厂函数的返回值一般都是基类指针,用户在使用这个指针之前,需要将这个指针转换到正确的类型指针。例如以下代码:
class CShape {...};
class CRectange : public CShape {...};
CShape* createRectange() {
 return new CRectange();
}
CRectange* pRect = static_cast<CRectange*>(createRectange()); //explicitly casting
可以看出,这就要求所有的类都从一个基类派生,就像MFC中几乎所有的类都有一个共同的基类CObject.

2。对于函数的参数,没有特别的要求。函数的参数可以用来区分要创建的对象类型,

例如以下的代码:
class CShape {...};
class CRectange : public CShape {...};
class CCircle : public CShape {...};
CShape* createShape(enum shapeType) {
 if(shapeType == RECTANGE) return new CRectange();
 if(shapeType == CIRCLE) return new CCircle();
}
在MFC中也有一个这样的例子,就是COleObjectFactory。根据类名就可以猜测出,COleObjectFactory是一个用来创建OLE object的类厂。COleObjectFactory的构造函数:
COleObjectFactory(REFCLSID clsid,CRuntimeClass* pRuntimeClass,BOOL bMultiInstance,LPCTSTR lpszProgID );
其中的前两个参数就决定了要创建的对象的类型。
然后,通过调用COleObjectFactory::OnCreateObject()来返回创建的对象。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值