当前位置:首页 > 百科

类工厂

class factory(类工厂) 一个实现了IClassFactory接口的类,这允许它创建特定类的对象,也被称为COM Class Object。类工厂的作用是在COM中,客户程序必须通过类工厂(Class Factory)来完成创建COM对象的任务。

  • 中文名称 类工厂
  • 外文名称 class factory
  • 任务 完成创建COM对象
  • 也称 COM Class Object

本功能

  类工厂的实质是一个COM对象,它定义了一个IClassFactory接口,正是这个接口中的CreateInstance成员函数,对实例化COM组件起到了核心作用。

  另外,根据COM规范,CO总汉走围手么M Class和类工来自厂是配对出现的。也就是360百科说,只要有一个实现某一个或周则色某几个接口的类被编写出来,若客户程序想对其进行实例化,就必须相应地实现与这个COM Class配对的类工厂。更还航具体地说,就是要实现IClassFactory接口。

  举个实际的例子,如果想要使用已经编写的一些类作一些事情,就必须实现类工给派火随露刻华答鱼那厂。反之,客户程序将无法访问到类的接口,那就不可能调用其成员函数。

  在COM中,客户程序必须通过类工厂(Class Factory)来完成创建COM对象的任务。

  注意:

  类工厂也被称为COM Class Object,可能这个叫法适怎免被氧现念转权京钟对理解类工厂的用途更有帮助。

况宪常顶穿帝细  为了透彻了解类工厂的运作机制,让我们看一看类次留路放音工厂的定义:

  class IClassFactory : public IUnknown

  {

 主尼威即受 virtual HRESULT Creat践行年清张同二洲eInstance(家技观于果议煤资获见LPUNKNOWN pUnk ,

  REFIID riid, void ** ppv) = 0

  virtual HRESULT LockServer(BOOL fLock) = 0;

  }

实现原理

  为COM对象实现类工厂,首先,进行类工厂的声明,代码如下:

  class CSimpleMath_Class情架天相就武你群妈Factory : public IClassFact龙干九持复笑唱ory

  // 声明用于实现IClassFactory接口的对象

  {

  protecte广可伯调财让似d:

  // 用于引用计数的成员变量

  long m_RefCount;

  public:

  CSimpleMath例脸密且树建无不装压进_MathClassFact是血际思职ory();

  ~ CSimpleMath_MathClassFactory();

  // 由于IClassFactory接口继承自IUnknown接口

  // 所以,也继承了IUnknown接口的三个方法

  HRESUL宁剧张认院图土T QueryInterface(REFIID, void** );

  ULONG AddRef();

  ULONG Release();

  // IClassFactory接口本身需要实现的方法

  HRESULT CreateInstance(LPUNKNOWN, REFIID, void**);

  HRESULT LockServer(BOOL bLock);

  };

  然后,具体实现的代码如下:

  CSimpleMath_ClassFactory:: CSimpleMath_ClassFactory ()

  {

  // 对象构造时初始化引用计数为0

  m_lRef = 0;

  }

  CSimpleMath_ClassFactory::~ CSimpleMath_ClassFactory ()

  {

  }

  HRESULT CSimpleMath_ClassFactory::QueryInterface( REFIID riid, void** ppv )

  {

  *ppv = 0;

  // 如果查询的接口为IUnknown或类工厂接口,则返回此实例

  if ( riid == IID_IUnknown || riid == IID_ISimpleMathClassFactory )

  *ppv = this;

  if ( *ppv )

  {

  // 如果成功地引用到接口,则增加接口的引用计数

  AddRef();

  return S_OK;

  }

  return(E_NOINTERFACE);

  }

  ULONG CSimpleMath_ClassFactory::AddRef()

  {

  m_RefCount ++;

  return m_RefCount;

  }

  ULONG CSimpleMath_ClassFactory::Release()

  {

  m_RefCount --; // 减小引用计数

  if (m_RefCount == 0 )

  {

  // 如果引用计数减少至0,则释放之

  delete this;

  return 0;

  }

  return m_RefCount;

  }

  // *****************************//

  // 用来产生COM对象的重要方法

  // *****************************//

  HRESULT CSimpleMath_ClassFactory::CreateInstance

  ( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )

  {

  CSimple_Math * p; // 声明指向COM Class的指针

  HRESULT hr;

  *ppvObj = 0;

  // 创建COM Class的实例

  p = new CSimple_Math;

  // 如果没有成功地创建对象,则返回错误值

  if (!p)

  return(E_OUTOFMEMORY)

  // 如果得到了对象,则可以调用QueryInterface方法

  hr = p->QueryInterface( riid, ppvObj );

  // 如果调用失败则做好善后工作,并将最终的状态返回

  if ( FAILED( hr ) )

  delete p;

  return hr;

  }

  HRESULT CSimpleMath_ClassFactory::LockServer( BOOL bLock )

  {

  if ( bLock )

  {

  // 注意:g_LockedCount是COM对象中声明的一个全局计数变量

  // 为了保障线程安全,需要对全局变量进行保护

  InterlockedIncrement(g_LockedCount) ;

  }

  else

  {

  // 注意:g_LockedCount是COM对象中声明的一个全局计数变量

  // 为了保障线程安全,需要对全局变量进行保护

  InterlockedDecrement(g_LockedCount);

  }

  return S_OK;

  }

  这样就完成了类工厂的具体实现。在整个实现代码中,最关键的部分使用粗体字进行了标注。经过这样一番精心实现之后,客户程序便可以通过实例化类工厂COM对象,进而得到类工厂的IClassFactory接口指针,然后,通过对该接口中核心方法CreateInstance的调用完成COM对象的实例化。剩下的事情不言自喻-- 尽情调用COM对象中的服务吧。

主要事例

  来自在开始介绍类工厂之前,先提一个小问题:

  下面代码产生错误的原因是什胶朝久江粮酸飞的管保么?

  class CFoolish

  {

  public:

  CFoolish();

  ~CFoolish();

  int m_count;

  …

  }

  int main()

  {

  CFoolish::m_count = 100;

  return 0;

  }

  答案实在太明显了-- 没有创建对象就要访问类对象的非静态成员,才出错。创建完一个接口,并按照标准COM的要求实现了它,使客户程序可以通过QueryInterface方法来得到对象中的接口。但是,有一个问题尚未解决,那就是,我们没有看到一行可以令COM对象在内存中胡前物刘维实例化的代码,因此,如果此时使用这个接口,就会犯与前面所提的简单问题中同种类型的错误。并且,需要提醒大家的是,由于COM对象的复杂性(360百科与前面所讲的引用计数一样),C执画似含茶黑行弱龙饭烟OM实例的创建仍然要依赖内部机制来管理,而不能像普通语言对象一样,由客户程序使用简单的new、delete来控制。

标签:

  • 关注微信

相关文章