软件复用的关键因素
前提:必须有可以复用的对象;所复用的对象必须是有用的;服用者需要知道如何去使用被复用的对象
COM组建标准的目标:
易于动态组装(复用和集成)
组件的实现与语言无关,对使用者(客户)透明。约束松
可以以二进制的形式发布
组件的升级不影响驶入继续使用它的老客户
组件可以透明地在网络上进行位置分配。对远程组件的使用和对本地机器上的组件的使用对客户来说无差别。
COM组件的结构:
-
由接口和实现两部分组成
-
实现部分对组件的客户来说是黑盒。客户能够看到的是组件的接口部分
-
接口部分由若干接口组成
-
每一个接口是有序排列的一组函数指针。可以简单理解为一组函数
-
每一个接口相当于该组件对外的一个窗口,客户可以从不同的视角(接口)看到,获得该组件通过该接口提供的服务。
-
对客户来说,组件就是接口集只能通过接口与组件交互。
类等价于概念
接口:约定,契约,条文,协议,(规范)
利益相关者多个,抽象出两类:
实现方:遵循约定的内容,做东西(结果)
使用方:遵循约定的内容,使用实现方做出的结果。
接口规定:(IUnknown)
-
对接口进行规定,是为了达到COM组件标准提出的目标
-
所有组件都有一个IUnknowm的接口(未名接口),该接口中依次给出了三个函数QueryInterface,AddRef, Release
-
QueryInterface的作用是对组件的接口进行查询,也就是:组件客户可以通过它查询该组件是否存在某一个接口(某一组功能)。若存在某个接口,客户可以获得该接口,从而获得该接口中提供的服务。这个规定是因为COM组件之间是动态组合的,对一个组件使用前,必须确认它具有所需要的服务。即:先确认,后使用。这与一般程序中对对象的使用时不同的。这一段话我们有几点需要理解:一个组件有若干个接口,肯定也有IUnknown接口
A想用B,A直接用B是不安全的,不确定B是否有某一方面的功能。而应该是这样的。客户程序查询该组件是否有某个接口。A先wenB是否会做某件事(即A问B是否承诺了某方面的事)(即A问B是否具有某一方面的接口。) -
AddRef和Release通过计数器共同完成引用计数功能
-
一个组件可以同时被许多个客户所使用,使用时需要载入内存。无论哪个客户把它载入内存,任何一个客户都不能决定何时把他从内存中卸载,因为不知道是否还有其他客户程序在用它。
-
为了知道何时这个组件没有客户,利用一个计数器来记录该组件的使用情况
-
实际上,可以为组件的每个接口安排一个计数器,用来记录每个接口的使用情况。当所有接口的计数器为0时,意味着该组件不存在客户了,可以从内存中卸载。
CI客户程序用组件A,先看内存中A是否存在,不存在的话,条件允许的话载入内存。已经在内存中,引用计数器加1 -
一个组件的其他接口可以看作IUnknowm的子接口,即:其他任何一个接口的前三个函数IUnknowm接口中的三个函数相同
-
客户获得一个接口后,可以查询其他接口是否存在,即:从任何一个接口,可以得到其他的任何一个接口。也就是,如果我们看到了一个接口,就相当于我们看到了整个组件。
-
与上面相关的一个规定对于某个Ix,一旦它可以从某个接口Iy查询获得,它便能够通过任何一个接口获得。(实现QueryInterface时的一个约束)
-
能够获得曾经获得过的接口(接口集不发生变化)
-
如之前所说,每个接口能够进行引用计数
-
接口规定(不变性)
-
一旦公布了某一个接口,该接口将永远不能发生任何变化。包括函数在接口中的顺序。
-
改变接口的唯一方式是:为组件增加新的接口。不允许向组件中已经有的接口增加新的函数
-
目的是兼容。版本升级不会影响老客户
-
一个接口有唯一的接口标识。对接口中函数的确定,本质上是通过位置确定的。