当前位置: 首页 > 工具软件 > JFace > 使用案例 >

jface随想

闻人志
2023-12-01

jface mvc随想

hanlray@hotmail.com

Revision: 1.0 Date: 2005/06/18


1. 以model为中心

在jface框架中,要把一个model用viewer表示出来,最重要的是写一个content provider,实现相应viewer要求的接口。这个content provider是一个adapter,它匹配model接口为viewer期望的接口,这样,model和view完全分离,model完全不需要知道view,因而易于变化的view不会影响到相对稳定的model。

在model接口已存在或定义好的情况下,要把model显示出来,我们只能在content provider上作工作,这是符合jface的设计思路的,但是更常见的情况是:写view时model还未定义(比如由一个人同时设计view和model时),这时候人们常常习惯先设计view的样子,然后根据view来设计model,此时如果思路不清晰,就容易把特定于某个view的东西带入到model中,从而从model隐式依赖于某个特定的view,从而丧失部分mvc的价值,同时这种方式也无助于发现真正的model并设计出真正反映应用逻辑的model接口。由此可知,view的展现方式也许是你设计model的出发点和考虑因素之一,但不应该是最重要的,model最终还是应该有应用逻辑本身来决定,这样设计出的model才能真正不依赖view,得到的model接口也更清晰易懂。

2. 另一种思路

各个content provider和label provider的实现所作的主要工作是把对一般化的content provider(IStructuredContentProvider, ITreeContentProvider等)和label provider接口的调用转化为要特定的某个model类型的接口调用,这个过程本身就可能是比较繁琐的,特别是当没model缺少一些需要的接口时还要给model增加新接口,而这种接口有可能只是为了适应某个view显示的需要,即使今后可能会发现这些接口真的是model应该有的,在当前阶段就增加这些接口仍然显得有些不合适。更恼人的是,这些content provider和lable provider必定会有一些if-else的调用,根据对象的类型做不同的处理,这显然是一种bad smell。

org.eclipse.ui.model包也许为我们展示了另外一种思路,它提供了几个content provider和label provider的实现,其中BaseWorkbenchContentProvider比较重要,它实现了IContentProvider, IStructuredContentProvider, ITreeContentProvider接口,其中IStructuredContentProvider的getElements方法的实现为:试图从传入的model对象得到IWorkbenchAdapter适配器接口,若能得到则委托给IWorkbenchAdapter的getChildren方法,否则返回空数组。那么如何得知model对象是否提供了IWorkbenchAdapter适配器呢? IAdaptable接口提供了方法getAdapter,接受一个class类型,若实现IAdaptable接口的model类提供了IWorkbenchAdapter适配器,则它对getAdapter(IWorkbenchAdapter.class)的调用就会返回一个IWorkbenchAdapter的实现。其他接口方法的实现与此类似,只不过委托为了IWorkbenchAdapter的其他方法。label provider的实现WorkbenchLabelProvider也是同样思路,仍然是委托给IWorkbenchAdapter的相应接口。

看起来这种方式只是把原来content provider做的工作转移到了model上,这样会带来model和viewer的耦合吗?我认为不会,因为model完全可以提供适应多个viewer的适配器。相反,这种由model来提供适配器的方式有以下几个优点:

  • 避免丑陋的if-else来判断对象类型

  • 以model中的匿名类,嵌套类方式事实现的adapter,可以方便的方位model的私有成员,而不需要提供不必要的接口方法

  • 对于一个model,其逻辑结构基本决定了其可能的显示方式,若由model提供这种显示方式的adapter,能简化model的显示,有利于代码复用

当然这种方式也是有缺点的,每增加一个新的adapter都需要修改model的代码,这就违背了Open-Close原则;另外,IAdaptable和IWorkbenchAdapter接口不属于jface,而属于RCP中一个重要的component(workbench),要在一个独立的swt或jface应用中使用可能还要作额外的工作。

 类似资料: