IAdaptable是Eclipse插件開(kāi)發(fā)中非常重要的一個(gè)接口,在整個(gè)插件體系中也起著舉足輕重的作用。網(wǎng)上也有不少文章來(lái)介紹這個(gè)接口的用法,因?yàn)槲覜](méi)有碰到那些文章中提到的一些IAdaptable應(yīng)用場(chǎng)景,所以開(kāi)始的時(shí)候?qū)@個(gè)接口不以為然:不就是一個(gè)適配器嗎?有那么重要嗎?隨著項(xiàng)目的進(jìn)展,IAdaptable終于讓我體會(huì)了它的好處。
先來(lái)介紹一下我的項(xiàng)目情況:我的項(xiàng)目是一個(gè)開(kāi)發(fā)工具插件,其核心就是各種xml配置文件的編輯器。編輯器的組件體系比較復(fù)雜,就像芭比娃娃,一成套一層的,比如多頁(yè)編輯器中套單頁(yè)編輯器,單頁(yè)編輯器中根據(jù)不同的內(nèi)容又分成不同的區(qū)塊,區(qū)塊還包含最終的編輯元素,比如text, combobox等等。而要編輯的內(nèi)容模型內(nèi)容以及相關(guān)的資源信息(比如IProject, IFile, IPath)大部分都位于組件結(jié)構(gòu)的最外層,比如IEditorPart, IEditInput中。
而不同的組件層次可能需要不同的信息,為了降低耦合度,我開(kāi)始定義和使用各種需要的資源內(nèi)容的提供接口,比如IProjectProvider, IModelProiver, IConfigProvider,ISelectionProvider等等,這樣最外層實(shí)現(xiàn)了一堆Provider,然后根據(jù)不同的需要往內(nèi)層傳,從外層到最終需要該資源的層之間不斷的傳遞,而中間起傳遞作用的各個(gè)層次都來(lái)實(shí)現(xiàn)這些IXxxxProvider接口。開(kāi)始一兩個(gè)還無(wú)所謂,后來(lái)需要傳遞的資源多了,層次多了,維護(hù)非常麻煩(如果增加一種需要的資源,就定義一個(gè)IXxxxProvider)。于是開(kāi)始尋找更好的方法來(lái)處理這種維護(hù)上的麻煩,一次偶然的機(jī)會(huì)在EMF generate的代碼中發(fā)現(xiàn)了IAdaptable接口的用法:
- public Object getAdapter(Class key) {
- if (key.equals(IContentOutlinePage.class)) {
- return showOutlineView() ? getContentOutlinePage() : null;
- }
- else if (key.equals(IPropertySheetPage.class)) {
- return getPropertySheetPage();
- }
- else if (key.equals(IGotoMarker.class)) {
- return this;
- }
- else {
- return super.getAdapter(key);
- }
- }
能不能將所有Provider合成一個(gè)呢?對(duì),這樣中間的各個(gè)層次之間只需要實(shí)現(xiàn)IAdaptable接口就可以了,如果發(fā)生變化,只需要修改兩頭:即資源提供者和資源消費(fèi)者,于是我的最外層定義了一個(gè)長(zhǎng)長(zhǎng)的IAdaptable的實(shí)現(xiàn)方法getAdaptable():
- public Object getAdapter(Class key) {
- if (key.equals(IContentOutlinePage.class)) {
- return showOutlineView() ? getContentOutlinePage() : null;
- }
- if (key.equals(IPropertySheetPage.class)) {
- return getPropertySheetPage();
- }
- if (key.equals(IGotoMarker.class)
- || key == IEditingDomainProvider.class
- || key == ISelectionProvider.class
- || key == IClipboardProvider.class
- || key == IAdapterFactoryProvider.class) {
- return this;
- }
- if (IProject.class.equals(key)) {
- return getProject();
- }
- if (BaseConfig.class.equals(key)) {
- return ((IConfigProvider) this).getConfig();
- }
- if (EObject.class.equals(key)) {
- return getModel();
- }
- if (DoradoXMLResourceImpl.class.equals(key)) {
- return ((IResourceProvider) this).getResource();
- }
- if (key == EditingDomain.class) {
- return editingDomain;
- }
- if (key == AdapterFactory.class) {
- return adapterFactory;
- }
- if (key == BaseActionBarContributor.class) {
- return getActionBarContributor();
- }
- if (key == Clipboard.class) {
- return getGlobalClipboard();
- }
- return super.getAdapter(key);
- }
如果這個(gè)數(shù)據(jù)模型是獨(dú)一無(wú)二的,就直接根據(jù)模型類(lèi)型返回模型,如果一個(gè)Provider可能會(huì)提供多個(gè)模型或者一種模型類(lèi)型對(duì)應(yīng)多個(gè)Provider那么就返回Provider,讓模型消費(fèi)者決定來(lái)獲取哪個(gè)模型。
雖然重構(gòu)為使用IAdaptable花了不少時(shí)間,但是對(duì)于后期的變動(dòng)卻少了不少的麻煩,而且代碼也減肥了不少。
安徽新華電腦學(xué)校專(zhuān)業(yè)職業(yè)規(guī)劃師為你提供更多幫助【在線咨詢】