插件开发中的IAdaptable另一种用法

IAdaptable是Eclipse插件开发中非常重要的一个接口,在整个插件体系中也起着举足轻重的作用。网上也有不少文章来介绍这个接口的用法,因为我没有碰到那些文章中提到的一些IAdaptable应用场景,所以开始的时候对这个接口不以为然:不就是一个适配器吗?有那么重要吗?随着项目的进展,IAdaptable终于让我体会了它的好处。


先来介绍一下我的项目情况:我的项目是一个开发工具插件,其核心就是各种xml配置文件的编辑器。编辑器的组件体系比较复杂,就像芭比娃娃,一成套一层的,比如多页编辑器中套单页编辑器,单页编辑器中根据不同的内容又分成不同的区块,区块还包含最终的编辑元素,比如text, combobox等等。而要编辑的内容模型内容以及相关的资源信息(比如IProject, IFile, IPath)大部分都位于组件结构的最外层,比如IEditorPart, IEditInput中。

而不同的组件层次可能需要不同的信息,为了降低耦合度,我开始定义和使用各种需要的资源内容的提供接口,比如IProjectProvider, IModelProiver, IConfigProvider,ISelectionProvider等等,这样最外层实现了一堆Provider,然后根据不同的需要往内层传,从外层到最终需要该资源的层之间不断的传递,而中间起传递作用的各个层次都来实现这些IXxxxProvider接口。开始一两个还无所谓,后来需要传递的资源多了,层次多了,维护非常麻烦(如果增加一种需要的资源,就定义一个IXxxxProvider)。于是开始寻找更好的方法来处理这种维护上的麻烦,一次偶然的机会在EMF generate的代码中发现了IAdaptable接口的用法:

java 代码
  1. public Object getAdapter(Class key) {   
  2.     if (key.equals(IContentOutlinePage.class)) {   
  3.         return showOutlineView() ? getContentOutlinePage() : null;   
  4.     }   
  5.     else if (key.equals(IPropertySheetPage.class)) {   
  6.         return getPropertySheetPage();   
  7.     }   
  8.     else if (key.equals(IGotoMarker.class)) {   
  9.         return this;   
  10.     }   
  11.     else {   
  12.         return super.getAdapter(key);   
  13.     }   
  14. }  

 

能不能将所有Provider合成一个呢?对,这样中间的各个层次之间只需要实现IAdaptable接口就可以了,如果发生变化,只需要修改两头:即资源提供者和资源消费者,于是我的最外层定义了一个长长的IAdaptable的实现方法getAdaptable():

java 代码
  1. public Object getAdapter(Class key) {   
  2.         if (key.equals(IContentOutlinePage.class)) {   
  3.             return showOutlineView() ? getContentOutlinePage() : null;   
  4.         }   
  5.         if (key.equals(IPropertySheetPage.class)) {   
  6.             return getPropertySheetPage();   
  7.         }   
  8.   
  9.         if (key.equals(IGotoMarker.class)   
  10.                 || key == IEditingDomainProvider.class  
  11.                 || key == ISelectionProvider.class  
  12.                 || key == IClipboardProvider.class  
  13.                 || key == IAdapterFactoryProvider.class) {   
  14.             return this;   
  15.         }   
  16.   
  17.         if (IProject.class.equals(key)) {   
  18.             return getProject();   
  19.         }   
  20.   
  21.         if (BaseConfig.class.equals(key)) {   
  22.             return ((IConfigProvider) this).getConfig();   
  23.         }   
  24.   
  25.         if (EObject.class.equals(key)) {   
  26.             return getModel();   
  27.         }   
  28.   
  29.         if (DoradoXMLResourceImpl.class.equals(key)) {   
  30.             return ((IResourceProvider) this).getResource();   
  31.         }   
  32.   
  33.         if (key == EditingDomain.class) {   
  34.             return editingDomain;   
  35.         }   
  36.   
  37.         if (key == AdapterFactory.class) {   
  38.             return adapterFactory;   
  39.         }   
  40.   
  41.         if (key == BaseActionBarContributor.class) {   
  42.             return getActionBarContributor();   
  43.         }   
  44.   
  45.         if (key == Clipboard.class) {   
  46.             return getGlobalClipboard();   
  47.         }   
  48.   
  49.         return super.getAdapter(key);   
  50.     }  

 

如果这个数据模型是独一无二的,就直接根据模型类型返回模型,如果一个Provider可能会提供多个模型或者一种模型类型对应多个Provider那么就返回Provider,让模型消费者决定来获取哪个模型。
虽然重构为使用IAdaptable花了不少时间,但是对于后期的变动却少了不少的麻烦,而且代码也减肥了不少。

你可能感兴趣的:(eclipse,数据结构,xml)