如何在保持松散耦合的同时通过Eclipse Selection Service处理来自不同提供者的选择?

时间:2015-03-15 02:33:54

标签: java oop design-patterns eclipse-plugin listener

TL; DR:有没有办法,最好是坚持设计模式最佳实践,从ISelection中的多个ISelectionProvider处理ISelectionListener s而不破坏松耦合,没有猜测(类型检查,铸造)?

在我的Eclipse RCP 3.7应用程序中,我有两个视图和一个(GEF编辑器。视图包含检查表,允许用户通过选择来控制编辑器的内容。假设编辑器显示大学人员层次结构,一个视图将允许选择应显示其员工的部门,另一个视图允许选择应显示员工的当前学位级别。

即如果用户在一个视图中选择计算机科学英语文学,并且 Post-Doc Full Professor < / em> * 在另一方面,编辑器将显示工作人员(例如,节点),这些人员来自CS或EngLit部门的Post-Docs或Full Professor。但是,该模型包含了所有部门的所有工作人员。

我根据Eclipse Workbench: Using the Selection Service实现了视图和编辑器:编辑器有org.eclipse.ui.ISelectionListener,视图都实现了org.eclipse.jface.viewers.ISelectionProvider。视图维护一个侦听器列表,每当选择更改时,都会在循环中通知:

((ISelectionChangedListener) listeners.getListeners()[i]).selectionChanged(
        new SelectionChangedEvent(DeptView.this, 
        new StructuredSelection({selection})))

到目前为止,我已经尝试了以下实现,但我对它们都不满意。

  1. 对于{selection},请使用自定义类(例如DeptSelection),它会封装所选元素,或者更确切地说是它们指向的模型元素。我认为 这会打破松散耦合,因为DeptSelection将在 Dept Plugin 中定义,它将与分开em>编辑器插件,同时我想允许客户端为听众也能听的选择添加扩展名。

  2. 对于{selection},只需传递所选元素(在本例中为org.eclipse.jface.viewers.CheckboxTableViewer#getCheckedElements()),然后在编辑器中的ISelectionListener#selectionChanged()中进行处理。这是笨拙,因为它涉及大量猜测:类型检查,转换等。此外,对于此解决方案,我然后将选择“保存”在抽象工具类SelectionUtil中,在编辑器中读取(这里是根编辑部分的内容编辑部分),以将相应的模型元素添加到AbtractEditPart的{​​{1}}返回的列表中。我(a)不确定使用抽象的util类是否会破坏松散耦合,以及(b)是否具有抽象的util类是一个好的设计模式

  3. 因此我的问题是:是否有一种非笨拙的方式,最好是坚持设计模式的最佳实践,在不破坏松耦合的情况下处理多个getModelChildren()

    * 我知道,不是最准确的例子,因为“正教授”和“博士后”不完全是学位。

2 个答案:

答案 0 :(得分:1)

查看Adapter PatternIAdaptable界面,并使用您的实际对象填充StructuredSelection,而不是仅为传达选择而创建的其他容器(您已正确识别为有问题)。

编辑:此外,https://eclipse.org/articles/Article-WorkbenchSelections/article.html

答案 1 :(得分:1)

您可以将您放置在选择工具IAdaptable中的对象设置为允许您查询实际需要使用的类的对象:

MyObject obj = ((IAdaptable)selectionObject).getAdapter(MyObject.class);

您的选择对象将包含:

public Object getAdapter(Class adapter)
{
  if (adapter == MyObject.class)
    return .... my object instance

  return null;
}

您可以更进一步使用IAdapterFactory类,它允许您使用完全独立的类来调整代码。类似的东西:

class AdapterFactory implements IAdapterFactory
{
  @Override
  public Object getAdapter(Object adaptableObject, Class adapterType)
  {
    if (adaptableObject instanceof MyObject && adapterType == MyObject.class)
      {
        ... convert from 'adaptableObject' to MyObject
        return myobject;
      }

    return null;
  }

  @Override
  public Class<?> [] getAdapterList()
  {
    return new Class<?> [] {MyObject.class};
  }
}

您可以使用适配器管理器或使用org.eclipse.core.runtime.adapters扩展点以编程方式声明工厂。

使用此适配器管理器从您的选择中查找对象:

MyObject obj = (MyObject)Platform.getAdapterManager().getAdapter(selectionObject, MyObject.class);

Eclipse本身使用适配器工厂方法从用户界面对象适应像IFile这样的东西。