【必修】组件考试向精简版笔记 chapter2 COM组件与接口

COM组件

1.COM组件要实现的核心问题就两个【COM规范的主要目标】:
1)支持动态连接;(通过每个接口都继承的IUnknown接口来实现QueryInterface)

2)支持向前兼容;
(已经实现的组件永远不被改变【老组件不变】,但可以添加新的组件,这样在版本更新后,就仍然能投入使用。)【COM接口的不变性约束】

还有一些其他目标:
语言无关;支持二进制表述;约束程度低,限制少。

任何一个COM接口都必须提供的接口:IUnknown【一种COM约束】

该接口提供三个函数:
①QueryInterface; ②AddRef; ③Release.

(非常重要,必考)

所有接口必须继承IUnknown,也就意味着所有接口都具有以上三个函数的功能。

QueryInterface 接口查询函数(改变状态函数)

1.功能:

客户要查询组件是不是能实现一个功能,就会先调用该函数,如果可以实现,就返回一个接口类型的返回值。
(实现QueryInterface时,参数不一定是一个,函数语法上的返回值类型也不一定是接口类型。)

即,在组件运行时,客户程序试图通过它来查询接口。

2.客户使用该函数的方式

为了满足合理调用,客户程序需要 先查询,后使用 。比如,若客户程序C查询组件S的某个接口Ix,那么它的意图是:

试图获得一个支持Ix接口的实现体,并不是简单地查看有没有。(如果查看到了是要用的)

3.QueryInterface的更高层用途

当客户查询到组件的时候,组件里可能有多个接口,每个接口都可以提供查询服务,无论客户查到了哪一个接口,它都可以用现在查到的这个来实现它想要的功能。

所以,可以把组件S的接口集看成是S运行时的状态集,每个接口对应一个合法状态。每个状态都支持QueryInterface函数调用,而该函数的调用,会导致S的状态变迁。

AddRef()和Release()函数【非常重要+1】

这两个函数是用来进行内存管理的。

它们都和一个计数器有关——AddRef()负责将这个计数器自增1,Release()函数负责将这个计数器自减1.

当计数器为零的时候,程序就知道这个接口没有被调用,就可以释放相应的内存空间。

Q——为什么规范约束每个组件必须有它们?
A——AddRef相当于载入组件;Release相当于释放组件,它们解决的事载入和卸载的时机问题:载入组件,相当于包括内存在内的资源占用,卸载组件则相当于资源释放。

Q——如果组件和一般的程序相同,就没必要给出额外的处理方案,操作系统可以按照一般程序的处理方案来处理,问题是,组件不是普通的程序,它有何特别之处?

A——支持动态连接。

Q——什么时候载入?
当客户程序C想要使用组件S的时候,可以请求系统载入S,如果S已经载入,系统可以把S的使用方式交给C,如果还没载入,则系统试图将它载入,然后将它交给C。

所以,用到S的客户程序作为一种触发因素,导致S载入。

Q——什么时候卸载?
多个用户程序中的任何一个程序停止使用S时都不能直接将S卸载,因为其他用户还在用。
有两种解决办法:
①操作系统集中管理;
②组件自己管理(分散式管理):引用计数器,为零的时候就卸载。(说明没人在用了。)这个时候组件就自己向系统提出申请,表示可以被释放。

【COM的其他约束1】

1.IUnknown实现的约束:
因为所有接口都实现IUknown中三个函数的功能,所以客户程序可以获得针对当前获得的任意一个接口,让组件做三个函数所对应的功能:

通过接口实现体查询其它接口,进而获得所查接口对应下实现体。

2.虽然,COM规范不约束实现,但因为每个接口都有QueryInterface函数,所以从组件的外在表现方面进行了与该函数相关的约束:
①一旦某个接口能够被客户程序查询到,那么它应该始终能够被查询到。
②一旦某个接口能被客户程序查询到,那么通过该组件的任何一个接口中的QueryInterface都能查到。
(而且还能变成相应功能)

【COM的其他约束2】接口不变性约束【向前兼容】

COM 组件一旦帆布,就不能对该接口做任何变化;
变化包括(接口内每一个函数的原型,函数的顺序等)

一个组件的接口不变,并不意味着组件不变,它有两种变化方式:
1)组件结构与实现无关;
2)可以添加新的接口。

【COM的其他约束3】唯一标识

除了具有一个容易理解的名字外,任何一个组件都有唯一的一个标识,组件的任何一个接口,也有唯一的一个标识。

COM组件的规范

可以理解为编程约束或建议,由接口部分和实现部分构成组成。
接口部分可以理解为一种对外的承诺,一个接口包括一组函数,这些函数表示当前组件可以实现某一方面的能力;
实现部分负责实现接口里面的函数,这一部分是不对外开放的。

COM

(一)名词解释

1.【2019】动态连接

定义:动态连接是一种可以让用户在应用程序运行时将组件替换掉的技术。组件能够动态地被调用和释放,即能够动态地被调用和释放,即能够在应用程序的运行过程中动态使用,不是在发布应用程序的时候就把组件和应用放在一起,而是分离的,只有程序运行的时候,组件和程序才有机地结合在一起。

动态连接涉及到的两个问题:
①动态连接需要解决的主要问题是信息封装,信息隐藏是动态连接的一个必要条件——对应的解决方案是接口不变性,还有就是接口的实现必须与接口分开,组件须以二进制的形式发布,具备语言无关性。

②为了运行时调用合理发生,就涉及到关系检查,为了支持动态连接,COM组件的QueryIterface()函数可以查询接口;AddRef()和Realease()可以进行加载和卸载。当计数器为0的时候,意味着该组件不存在客户了,可以从内存中卸载。

动态连接的关系在运行时实现,此时已无连接程序,需要其它手段予以实现。动态连接适用于变化,从而不必在开发时进行充分设计,开发效率相对高。动态连接是组件的最基本属性。

2.【2019】COM组件技术中的IUnknown接口

Iunknown接口的存在,是接口规定的体现:
1)所有组件都应该有一个Iunknown接口,也叫未名接口;
2)该接口中依次给出三个函数,分别是:QueryInterface,AddRef,Realease;
3)“先确认,再使用”:QueryInterface的作用是对组件的接口进行查询,客户可以通过这个函数查询到组件中是否存在某一个接口,即是否能实现某一功能;
4)AddRef和Realease函数实现计数功能,体现加载和卸载,方便同一个组件同时被多个用户使用。

3.请阐述动态连接的基本原理。
①所有的COM接口都继承了Iunknown类,每个接口的虚函数表中的前三个函数都是QueryInterface,AddRef,Release;这使得所有的COM接口都可以被当成Iunknown接口来处理,因此任何一个接口都可以被客户用来获取它所支持的其他接口。

②同时,动态连接需支持多用户使用,AddRef()和Realease()函数可以使得组件进行自我管理,进行加载和卸载,当计数器为0时,说明该组件没有用户了,也就可以进行卸载。

(二)简答题

1.【2016】【2017】复用已有的COM组件,可以设计并实现新的COM组件,但对于任意一个COM组件,如果支持被其它COM组件复用,需要进行合理的设计.在考虑允许被其它COM组件复用的情况下,叙述利用动态链接库设计并实现一个COM组件的一般过程. (10分)
①定义业务接口,各接口都能继承Iunknown接口;
②为每个组件和接口分配唯一一个标识符;
③ 实现类厂接口以实现动态生成组件;
④ 编写DLL,在DLL函数中有注册表的函数,取消注册的函数,与类厂相连接的函数。

实现COM接口的一般步骤:
1) 定义各个业务接口,各接口都继承自Iunknown接口;
2) 为各个接口分配唯一标识符;
3) 实现各个接口的功能;
4) 定义类厂接口并分配唯一标识符;
5) 实现类厂接口以便实现动态生成组件;
6) 编写DLL,在DLL函数中有注册组件到注册表的函数,取消注册的函数,与类厂相连的函数。

利用动态链接库实现com组件时,如何定义导出函数的函数原型?
导出函数就是已编好的com组件供客户程序使用的函数。
① 先将需要输出的函数用extern”C”标记,这可以放置编译器修改函数名称(例如加上类型信息);以为变换以后的函数是不可移植的,并且对这种变换以后的名称处理起来也非常困难。
② 需要告诉链接程序需要输出的函数名。为此,需要建立一个def文件,将要输出的函数名称加到词文件当中,客户程序再通过到处函数名称获取此DLL中的导出函数地址赋予相同参数和返回值的方法指针。

2.【2017】概述COM组件技术规范的主要目标,即回答利用该规范开发软件有什么好处?
主要目标:动态连接,向前兼容,不限制语言,约束程度低,支持分布式计算,对远程组件的使用和对本地机器上的组件的使用对客户来说没有差别。

3.【2017】什么是动态连接?动态连接需要解决的主要问题是什么(或者有哪些)?
1)动态连接是运行时连接,不同于静态链接,在不使用的时候,各部分功能都是独立的模块,只有在使用的时候才会根据功能的不同对模块们进行组合调用。

2)静态连接需要对连接的合法性和合理性进行检测。解决办法是:关系的合理性检查,由调用者和被调用者自己解决。即“先查询,后使用”,COM的QueryInterface()提供了这一查询功能。

动态连接涉及到的两个问题:
①动态连接需要解决的主要问题是信息封装,信息隐藏是动态连接的一个必要条件——对应的解决方案是接口不变性,还有就是接口的实现必须与接口分开,组件须以二进制的形式发布,具备语言无关性。

②为了运行时调用合理发生,就涉及到关系检查,为了支持动态连接,COM组件的QueryIterface()函数可以查询接口;AddRef()和Realease()可以进行加载和卸载。当计数器为0的时候,意味着该组件不存在客户了,可以从内存中卸载。

4.【2017】从语义及作用的角度,简述你对QueryInterface函数的理解.

5.【2017】【2018】简述你对引用计数器作用的理解.
因为组件要支持动态连接,所以就必须允许多用户同时使用一些资源,为了进行内存管理,所有的借口都要有IunKnown接口,它实现的AddRef和Realease接口作为“增”和“减”函数,从而协助内存管理程序进行管理(接口通过这个方式进行自我管理。)

6.【2017】结合工厂方法设计模式,简述你对工厂(类厂)接口作用的理解.
1)客户可以通过类厂组件创建其他组件;
2)类厂组件的唯一功能就是创建其他组件;
3)创建组件的标准接口是IclassFactory,由它来创建;
4)建好一个组件后,可控制组件装载到内存中何处或检查客户是否有权限。

6.1 类厂方法产生的背景:
CorCreateInstance的灵活性不足以满足所有组件的需求,这种不足主要体现在没法提供一种能够控制组件创建过程的方法。问题的关键在于如何控制组件的创建过程。

在这里,我们并不需要关心组件的初始化,因为在创建好组件之后,可以通过一个接口来初始化它;但是在建立好一个组件之前是无法获得它的某个接口指针的,因此就无法对组件的创建加上条件限制。

解决这个问题的方法就是工厂方法设计模式,也就是类厂。CorCreanteInstance实际上并没有直接创建COM组件,而是创建了一个类厂组件,这个组件的唯一功能就是创建其它组件。这样用户就通过它获得了接口。

7.【2018】某研发小组在已有的COM组件V1版本基础上,开发了该组件的新的版本V2版,并遵循接口不变性约束,未改变V1版的任何已发布接口,那么,对于V1版的已有客户程序来说,能否直接利用V2版取代V1版?若能取代,使用V2版的效果与使用V1版的效果是否一定相同?为什么?

① 可以直接利用V2版本。这是因为组件的接口不变性,为了向前兼容,之前发布过的接口都不可以被更改,只能增加新的接口。所以可以取代。
② 不一定相同。因为v2版本可能通过添加新的接口来完成新的功能,或在不改变原有接口的基础上使得之前的功能被更新。

8.【2019】概述COM组件支持动态连接的基本原理。
所有COM组件都有Iunknown接口,在这个未名接口中包含有三个函数,分别是QueryInterface,AddRef,Realease这三个。

其中,QueryInterface与支持动态连接密切相关;当用户要使用某个功能的时候,需要先查询,再使用。他首先通过QueryInterface来查看组件是否具有某个功能,就是通过QueryInterface来查询的。

要动态链接,就必须使得运行时的组件可以同时为多个客户提供服务。为了解决何时载入和载出的问题,需使用AddRef()和Realease()方法。

9.简述com组件与程序模块的不同之处。
COM组件易于动态组装,组件的实现与语言无关,对使用者透明,可以以二进制形式发布;组件的升级不影响试图继续使用它的老客户;
模块是指整个程序中一些相对独立的程序单元,每个程序单元完成和实现一个相对独立的软件功能呢。通俗来说,是一些功能独立的程序段。模块是面向应用的基本单元,由一个或多个相同组件类型的组件组成。

组价必须首先封装到模块中,连同部署描述文件一起绑定到某个指定的文件中。而模块可以作为单独的软件单元分别进行部署,也可以进一步封装为更复杂的装置,来构造一个可以应用的软件系统。

10.每个组件有唯一的标识,每一个接口有唯一的一个标识。概述这里的标识是如何定义或产生的。
GUID的声明和定义:
Extern”C” const IID IID_IX;

11.采用何种手段区分不同的组件
用户和组件交流时是通过接口完成的,如果能够判断两个接口是否是同一个组件中的接口就可以区分是否是同一个组件。
而每个组件都有唯一的Iunknown接口,利用Iunknown接口的值,查询这个接口的值,如果相同则说明两个组件是同一个组件,如果不同则不是。

代理模式Proxy

  1. 【2016】【2018】代理模式能够解决什么样的或者哪些设计问题?(4分)

① 需要为一个对象在不同的地址空间提供局部代表时,使用远程代理;
② 按照需要创建开销很大的对象原始对象访问时,使用虚代理;
③ 需要控制对原始对象的访问的时候,可以使用保护代理;
④ 需要在访问对象的时候执行一些附加操作,使用智能指引代理;

  1. 【2016】【2018】简述代理模式解决问题的基本设计方法或设计思想(4分)
    代理模式的本质:控制对象访问。
    代理模式通过代理目标对象,把代理对象插入到客户与目标对象之间,从而为客户和目标对象引入一定的间接性。正式这个间接性,给了代理对象很多的活动空间,代理对象可以在调用具体的目标对象前后附加很多操作,从而实现新的功能或是扩展目标对象的功能。代理对象甚至可以不去创建和调用目标对象。

从实现上来看,代理模式主要是使用对象的组合和委托,尤其是在静态代理的实现里面会看得更清楚。但是也可以采用对象继承的方式来实现代理,这种实现方式在某些情况下比使用对象组合来得还要简单。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值