【说明】
引用了组里面的一架构师的文章,写的很好的,尤其是偏于抽象的部分。希望对新手有用。
使用CommonNavigator开发资源管理器--模型篇
在基础篇中,已经通过例子初步说明了,如何基于CNF制作一个简单的资源管理器,但很多开发人员并不理解,树上的结点是如何得到的,这就涉及到CNF的模型。在详述CNF的模型之前,需要先对Tree所使用的模型进行描述。
对于早期习惯C/S开发的程序员来说,对于SWT中的Tree并不陌生,可以通过相应的TreeItem来创建子结点,但是这并不是一种好的设计和使用方式,它大大的增加了模型与UI之间的耦合度,所以在Swing中,使用了TreeNode来描述树模型,而Eclipse则通过JFace提供了ITreeContentProvider接口来描述树模型。这两种方式有异曲同工之处,大家可以看一下这两个接口,就会发现两者非常之雷同,最大的区别在于前者通过userObject持有真实的数据,而后者则是由TreeItem的getData来持有,在使用的时候,才会由相应的TreeViewer传给ITreeContentProvider,从结构来说,后者是一个纯粹的控制类,而TreeNode则是更灵活一些,可以作为一个控制类,也可以作为一个模型体,所以相对而言,TreeNode更加灵活一些,但从本质上而言,两者并无区别。
表面上看来,一个TreeViewer将会拥有一个ITreeContentProvider用来取得树状的数据模型,进而呈现出来,但CNF中的树却更加灵活,在基础篇中,展现的图中,却表示可以通过扩展点org.eclipse.ui.navigator.navigatorContent来添加新的结点,而且这些与资源并没有本质的关系,它可以与一个具体的文件或者目录资源绑定,也可以与多个具体的文件或者目录绑定,还可以是一个与文件或者目录无关的模型。那么现在来看一下CNF到底做了哪些事情,使得它的模型扩展如此容易呢?
首先启动Eclipse32.,然后创建一个新的工作区,再将CNF相关的代码以插件的形式导入到这个工作区中,开始我们的分析过程。
讲到这里,要提到Eclipse提供的一个接口IWorkbenchAdapter和IWorkbenchAdapter2,这两个接口是有一点点怪的,因为从设计的角度来看,它将模型与展现层混合在一起,违反常见的设计准则,但从另一个角度来讲,它可以减少用户扩展的内容,有利于用户开发。由此可见设计准则并不是一成不变的,很多时候,它也要在易用性和合理性方面做出适当的妥协。这一点也可以在我们自己的设计中加以考虑,设计并不是要偏向哪一个方向,恰恰相反,设计是要在多者之间,如易用性,稳定性,合理性之间取得一个平衡点,而不是在各方面都做到完美。
另外ITreeContentProvider有一个方法getParent(Object parent),它是用来为一个指定结点找到相应的父亲结点,从而便于查找和定位,而这个方法却被很多人所忽视,开发人员经常会习惯性的直接返回null,而且也不会出现什么错误,但这个方法其实却是一个非常有用的方法,开发人员在使用Java资源管理器的时候,有一个经常使用的功能就是LinkWithEditor,这个功能经常是用来在资源管理器上定位当前打开的文件,这个功能如此之重要,以至于CNF专门为此定义了一个org.eclipse.ui.navigator.linkHelper来支持该功能。所以请根据实际情况,来实现这个方法,否则就无法正确的实现相应的功能。
以上对TreeViewer的模型进行了简单的介绍和分析,接下来就看一下CNF是如何处理树模型从而获得如此高的灵活性。
CNF很好的利用了代理模式,它自身并没有提供模型的能力,所以它将提供模型的能力仍然交给外部扩展点提供的类,它会根据当前要处理的结点,以及每个扩展点的表达式,来找出能够处理当前结点的ITreeContentProvider实例,然后再将这些实例返回的子结点放入相应的Set中,最终以数组的方式返回给TreeViewer,从表面上来看,可能很难理解正常情况下,每个TreeViewer只有一个ITreeContentProvider的模型接口,如何能够从多个实例中取得模型呢?就是由NavigatorContentServiceContentProvider这个代理类完成模型的组合功能。
因此只要提供自己的ITreeContentProvidre实现,然后通过扩展点挂入,即可将各种真实或者虚拟的模型挂入系统。
本博客中的所有文章、随笔除了标题中含有引用或者转载字样的,其他均为原创。转载请注明出处,谢谢!