Web Services的概念,应该是组件的Web版本!

来源:互联网 发布:嘉兴菜鸟网络招工吗 编辑:程序博客网 时间:2024/06/05 01:55
什么是COM
       关于是什么是COM,读者可以参阅本文后面的参考书目,因为对于概念的阐述这些书应该更加详细和系统。本文的目的只是想让大家在捧起一本厚厚的书之前,对于COM有一个整体的感性认识,从而知道为什么以及如何学习COM
 
为什么使用COM
       一个复杂的系统总是有很多的子系统,子部件组合而成的,建一座高楼如此,构造一个软件亦是如此。最明显得莫过于我们的机械行业了,大部分的零部件都有相应的国家标准或是国际标准。记得上大学的时候,学机械制图,就要学会查各种零件的规格尺寸。标准统一的好处就是,部件之间可以很好的相互配合工作,减少了生产和维护成本。比如,你的自行车坏了,只要到商店里买一个同样的零件换上而并不需要是原厂生产的,就可以解决问题。
         这样一个简单的问题在我们传统的机械行业里是多么地自然,以至于没有人意识到。然而同样的问题,到了我们的软件行业,好像就出了问题,我们没有这样一套所谓的国际标准。
        COM的出现就是要解决这个问题,它定义了一套二进制的接口规范。符合这套规范的组件就可以比较容易的相互连接,从而达到代码重用和互换。现在COM的发展远没有达到机械行业的标准化规范,也就是说没有一个个标准的组件,就像各种型号规格的螺丝钉一样。COM组件现在可以用一种统一的接口连接起来,并很好的运行了,但是中间的组合过程还是比较的麻烦和费力。也就是说,我们需要发展标准组件,象螺丝钉一样的标准组件!
         以后的软件开发应该就像现在的机械行业一样,工程师设计图纸,然后工人根据装配图组装各种组件!也就是说,大部分的部件是采用标准件,只有特殊部件要自己开发。这对节约成本、提高开发效率和降低维护成本都是大有好处的。
         在对照我们现在的开发,就知道还处在于手工作坊阶段。就像当年的工业大革命一样,我们软件行业也在企盼着软件工业化革命的到来。
         半导体工业也经历了这样一个产业化过程,现在你可以查到各种标准的电阻、电容和集成电路。最明显得就是电脑了,到中关村随便找一个人,你就可以组装起一台电脑,零部件虽然各异,到最后电脑的功能却都是一样。
 
COM的历史和未来
         COM最开始是微软的DDE(动态数据交换)技术,本意是在不同的应用程序之间交换数据(剪切板的概念应该就是那时候发明的吧)。后来DDE技术逐渐地变成了OLE(对象链接和嵌入),对象可以在其他的应用程序中激活。在OLE2中,逐渐就分离出了COM的概念。OLE技术是很复杂的,除了微软自己的Office产品,其他的厂家是很难有掌握的。Internet的流行,微软于是在OLE的基础上推出了ActiveX技术,欲与Java抗衡。ActiveX应该是OLE的简化版本吧,是实现了一系列标准接口的COM对象,可以嵌入IE浏览器运行。在推出COM之后,为了适应分布式计算的需要,微软推出了DCOM(分布式的COM)COMMTS(微软事务服务)的结合得到了COM+COM不同的是,COM+增加了事务的支持,同时也增强了COM的可管理性,COM对象处于一种受控状态,运行在一定的Context下面。
 
         可以说COM在微软的产品系列中真的是无处不在,对于Windows的发展功不可没。通过COM的标准二进制规范,使得不同程序语言开发的软件模块可以相互调用,开发效率大大降低。特别是对Dispatch接口的支持,使得脚本语言也可以调用COM组件,开发速度更是加快乐不少。
 
         但是COM毕竟只是微软自己的标准,并没有很好的在其他的系统平台上得到支持。ActiveX技术并没有能阻止Java,随着互联网的不断发展,Java也蔓延了整个世界,Java 让操作系统的界限变得模糊了。
        
         Java 仅仅解决了应用程序在不同的操作系统上的运行问题,并没有解决不同的应用程序之间如何交换数据这个难题。随着网络的发展,各种应用越来越多,相互之间的交互越来越频繁,数据交换的问题变得越来越尖锐。这时候,XML诞生了。XML是一种数据描述语言,有着强大的扩展功能。各大厂商纷纷支持XML,并在上面开展各种应用。
        
         Java+XML应该是互联网时代的解决方案了吧,真正实现跨平台了。但是微软并没有就此罢休,推出了Web Services的概念。这应该是组件的Web版本吧,通过 SOAP协议封装数据请求/结果,通过网络访问服务器上的服务。这是一种不同于传统的Web页面访问方式,而更像是程序式的访问。
        
         SOAP取代DCOM,可以跨平台,跨越防火墙,看来是微软对分布式计算的解决方案。从微软的My Services战略就已经可以看到这样的趋势。
 
         与此同时,微软还提出了.NET战略,其中就包括公共语言库的概念。Java类似的一点就是.NET平台上的开发语言都要编译成一种中间语言,最后由虚拟机对中间语言进行解释执行。对于中间语言,有一套规范,也就是说所有的.NET兼容语言必须能够编译出规范的中间语言。中间语言的出现,使得COM的存在没有了意义,因为中间语言是规范的,那么就没有必要使用COM的二进制规范了。有了中间语言,不同语言编写的模块就可以直接调用,所有的语言使用同一个开发库!
         较之于Java .NET提出的公共语言更能吸引程序员的注意。因为你不需要学习一门新的语言,不需要抛弃原来的代码,就可以平滑的转移到.NET平台。如果你学习.NET的原生(Native)语言,更会发现原来COM的许多技术在这里得到了多么好的实现,而且是那么自然,因为一切都是与生俱来的。
         虽然在.NET平台上,你仍然可以使用COM组件,但是随着.NET组件的增多,COM将逐渐淡出。
 
相关的概念
 
接口(Interface)一组函数入口的集合,是对象访问的入口。在很多现代的OOP语言里都有Interface的概念,很类似于C++里的纯虚类。不同的地方是,只能包含方法,不能包含成员变量。而且,只能继承接口的规范,不能继承接口的实现(Implement)。接口把对象的访问规范和对象的具体实现进行了分离。每个接口都必须从IUnknown接口继承(直接/间接)

IUnknown
接口:相信每一个刚学习COM的人都会感到疑惑,这是一个什么东西啊?其实在很多OOP的语言或是类库里都有最初的基类。在C#Java里都是Object类吧,在MFC里是CObject类。只不过在COM里,这个基类不叫做IObject,而叫做IUnkown而已。想来COM的发明人也挺幽默的。对于这个叫法的另一个解释,也许是基于这样的规定――――每一个COM对象都必须至少支持IUnknown接口。但是,一个只支持IUnknown接口的COM对象是没有任何作用的,因为使用IUnknown接口你什么也干不了。

COM
对象:实现了一系列接口的代码实体。一个对象可以支持多个接口。
 
COM对象和接口的差别:接口是访问规范,而COM对象是具体接口的具体实现。
 
标识:每一个接口都有一个标识,一般用IID_XXX表示。每一个COM对象也有一个标识,一般用CLSID_XXX表示。为了防止重名,前面的IIDCLSID都使用了GUID(全球唯一标识)来作为标识符。
 
IUnknown的三个函数:
COM规范规定了,每一个COM对象都必须支持IUnknown为什么呢?这就好比一个人到外国去旅游,他必须会一种通用语言,比如英语/汉语等等。这里,COM规定为IUnknown
COM
规范还规定,如果一个对象支持多个接口,那么从任意一个接口都应该能够访问到其他的接口也就是说,我会问你,“Can you speak Chinese?”。如果你会,你要说,“Yes ,I can”。同样,如果我问你,“你会说英语吗?”。如果你会,当然也要回答,“是的,我会”。如果不会,当然要做出否定的回答,这样别人就不会使用你听不懂的语言和你对话了。
那么在COM里是如何发问的呢?这就是IUnknown的三个最基本的函数之一QueryInterface,还记得吗,IUnknown是所有接口的基础,所以每一个接口都实现了这个函数。调用QueryInterface的时候,你需要指明需要查询接口的IID,像这样“请问你支持XXX接口吗?”。如果成功,会返回一个接口的指针(引用)所以,只要取得对象的一个接口,你就可以访问到它所有的接口。
IUnknown接口的另两个函数是AddRefRelease,主要用于管理COM对象的引用计数。在COM对象的使用中,你每取得(引用)一个接口指针,就必须调用该接口的AddRef方法一次,而在不再需要这个指针时,要记得调用Release方法一次。这好比你进入了实验室作实验,进去的时候登记(AddRef,使用计数加一),说明你要使用这个房间的设备。而在你离开的时候,要记得登离(Release,使用计数减一),表明你已经不再使用这个房间的设备了。为了节约电和安全,我们要求在实验室没有人使用的时候必须拉下电闸。所以你每次离开的时候必须确认实验室是否还有其他人在使用,最好的办法就是检查登记记录(你不能直接看实验室里是否有人来判断,因为别人可能临时出去了)。如果使用计数为零就表明没有人了,可以切断电源。而如果计数不为零,就表明还有人正在使用,你不能切断电源,直接走人就是了。
如果有人离开的时候实验室的时候忘了登离(Release),那么实验室的电源永远也不会被关掉,因为别人会认为还有人在实验室。而如果有人进去的时候忘了登记(AddRef),那么就有可能在实验的中间被人突然拉下电闸,因为别人不知道还有人在里面作实验。
 
COM对象里,计数的管理是在内部进行的,使用者不用考虑,也不用亲自删除对象(拉下电闸),只需要正确调用AddRefRelease就可以了。另外,当调用QueryInterface的时候,COM对象内部一般已经自动调用了AddRef的操作,所以不需要再调用AddRef了,但在最后要记得调用Release