懂COM的大虾请留步,请教您一个小问题! (50分)

  • 主题发起人 Archerfl
  • 开始时间
A

Archerfl

Unregistered / Unconfirmed
GUEST, unregistred user!
 学过COM原理的人都知道,在COM当中有类厂这个概念,它无非是要提供接口去创建相应的
COM对象。但是,我不太清楚为什么在COM的实现当中要用到类厂呢?直接创建COM对象不是更
好吗?请各位大虾指教,谢!
 
是进行实例化的吧?
 
找到了下面的资料:


类对象
这个类对象是一个特殊的 COM 对象,它的主要目的是实现 IClassFactory 接口。(您将
经常听到这个对象被引用为“类工厂”,甚至“类工厂对象”,但是更准确地应该引用为
类对象。)

如果您经常使用 Java,可以粗略地将 COM 类对象看成一个 "Class" 类的 Java 对象。而
且您将发现 Java 的 Class.newInstance 类似于 IClassFactory::CreateInstance,COM
的 CoGetClassObject 类似于 Class.forName 静态方法程序。

这个对象是特殊的,因为与大多数 COM 对象不同,它不是通过调用 CoCreateInstance 或
IClassFactory::CreateInstance 创建的。相反,它总是通过调用 CoGetClassObject 创
建的。在本篇文章的末尾,我们将看到特殊 COM 对象的其他实例。(正如所证明的,
CoGetClassObject 并不总是创建一个类对象。如果 COM 有正确类的一个类对象,它可以
只返回该类对象的一个接口指针。)

在调用 CoGetClassObject 之后,代码不必关心它创建了哪种对象,例如不管该对象是一个
进程内服务程序还是本地服务程序。类对象管理所有这些差别。为了知道如何创建和查找
CLSID 所需的一个类对象,CoGetClassObject 不需要查找注册表(以及已有的注册了的
类对象的列表)。

类对象是多态性的强大的一个良好实例。为了得到该对象,我们调用一个 COM API。但
是,当得到该对象之后,我们可以断定它支持所需的标准接口 (IClassFactory),然后
可以调用该接口的方法程序,这里是 IClassFactory::CreateInstance。注意,我们还
不知道类对象的 CreateInstance 是如何工作的。所知道的一切是,如果它成功了,它
会返回一个指向该对象的接口指针。我们不必也不想知道别的了(即封装内容),而且
通过进行相同的函数调用(即多态性),可以得到特定类对象的正确行为—正是类对象
的一致性确定了正确的行为。

每个类对象实例都与一个特定的 CLSID 相关—注意,IClassFactory::CreateInstance
不需要一个 CLSID 作为它的参数。相反,类对象知道要创建什么 CLSID。这意味着,对
于您想要创建的每个单独的 CLSID,至少需要一个类对象。

除了 IclassFactory,类对象可以实现任何接口。例如,您可以定义一个接口,该接口
允许为从特定类对象创建的对象实例设置默认行为。但是,要注意,并不能保证对于一
个给定的 CLSID,只有一个类对象,所以如果您多次调用 CoGetClassObject,可能会得
到指向不同类对象的接口指针。(由于您可以控制类对象的创建,可以在实现过程中定
义这一点。)

为什么要有一个类对象
正如我们讨论过的,COM 需要实现一个类对象的最重要原因是,这样 COM 可以具有创建
任何种类对象的标准多态方法,而客户程序不必知道创建过程的确切细节。类对象封装
了这些内容,这样客户程序就不必知道。这暗示着,类对象和“真正的”对象具有非常
紧密的关系—并且经常互相很了解。

但是,为什么不采用一个更简单的方案呢?例如,您可以想象在您的 COM DLL 中有一
个函数,就叫 DLLCreateInstance 吧,它可以接受一个 CLSID,并且创建一个新实例。
一个函数,比一个 COM 对象和 IclassFactory 要简单地多吧。

但是,它无法为 EXE 工作。您不能从 EXE 导出函数。而且,该函数也肯定不能很好地
为远程对象工作。所以,当我们让类对象作为一个 COM 对象时,COM 会照顾所有的进
程内和线外问题。这是个好买卖。

由于类对象是一个知道如何正确创建目标对象的实例的 COM 对象,注意,一旦创建了
类对象,对于创建实例来说,COM 就不相关了。所以,对于所创建的特定类型的第一
个对象,COM 必须做大量工作。首先,它需要在注册类对象列表中查找 CLSID(或者,
如果不存在类对象,就在注册表中查找)。如果需要创建类对象,COM 会创建它,可
能包括加载一个 DLL 或启动一个 EXE。最后,COM 调用正确类对象的
IClassFactory::CreateInstance 来创建您的实例。哇塞!

但是,如果您保留该类对象,对于后续实例,您可以越过大多数工作:为了创建其他
对象,只需自己调用 IClassFactory::CreateInstance。这几乎与直接接通接线员一
样快,而比让 COM 创建新对象要快得多。

重要内容 如果您保留一个类对象,则必须调用 IClassFactory::LockServer,以便
告诉 COM 将服务程序保留在内存中。对类对象的引用不会自动将服务程序保留在内
存中。这个行为是 COM 常规行为的例外。如果您不能锁定服务程序,在服务程序卸
载之后,试图访问类对象就有可能造成一个保护性错误。当您处理完类对象之后,不
要忘记解锁该服务程序。

最后,类对象支持创建对象的其他方法,例如使用 IClassFactory2 接口,而不使用
IClassFactory 创建许可控件。许可控件是在创建该控件之前需要用户拥有正确许
可 ID 的控件。
 
我也在学习中。不知道理解的对不对。
ClassFactory是一种设计模式。
1、COM库不知道创建对象的细节,所以需要厂类
2、从更大的粒度上控制组件的生命周期
3、实现创建对象的多态性
 
多人接受答案了。
 
顶部