| |
扩展refactoringwizard 框架 eclipse中的refactoringwizard框架扩展了eclipse的wizard框架,关于wizard框架的介绍可以在eclipse的帮助系统中找到,这里我们仅从oo设计和架构的角度探讨一下refactoringwizard框架。 我们从wizard相关的几个类开始: 1. wizardpage类 wizardpage是一个包含了多个界面元素(比如文本框text,按钮button)的一个界面组合部分。各个page之间是独立的,是可以动态加载的。wizardpage类的职责有: ?组合swt界面元素,构造出一个界面页。 ?定义本身界面元素的操作行为。 在refactoringwizard框架中预设了两个通用的属性页:previewwizardpage和errorwizardpage。previewwizardpage类是用来预览重构后的修改,对比代码或其他资源的变化。errorwizardpage类是用来处理条件检查及错误状态通知的。我们只需扩展refactoringwizard框架就可以自动获取这两项强大的功能。 2. wizard类 一个wizard就是一个装载一系列wizardpage页的容器,wizard类的职责有: ?装载一系列wizardpage,构造出一个复杂的界面。 ?装载领域类来处理具体业务逻辑。(在refactoringwizard框架中这个类就是refactoring类) 维护wizardpage页之间以及页与领域类之间的数据传递和状态共享。(在这里要补充一点,其实在具体refactoringwizard框架的实现中有专门的类来分担这部分职责。) 我们的界面行为可以千变万化(通过组合不同的wizardpage),而负责处理业务逻辑的领域类也可以独立的变化,你可以随意扩展wizard的界面功能(-对扩展开放),而不用修改现有refactoringwizard框架(-对修改封闭),这正是oo设计的最基本原则-ocp(open-close principle)。 3. wizarddialog类 这个对话框类的主要职责是构造一个完整的gui界面以及操作界面。它预设了一些按钮(back,next,finish,cancel)等界面元素,它负责装载wizard类,操作时通过按钮back、next来在多个wizardpage之间切换。 下面我们给出refactoringwizard框架的架构图:  图 5 refactoring wizard架构图 从图 5中我们可以看到,如果我们把每一个wizardpage页看作一项业务,那么refactoring正是处理业务逻辑的控制中心,它封装了所有对业务逻辑的处理,当然它可以在将处理任务委任出去。但请注意,它并不负责实现业务流程,也就是说各业务(各个page界面)之间的逻辑顺序关系不由它维护。 refactoringwizard框架充分考虑到了应用的可扩展性,它在swt的mvc(模型-视图-控制)元架构模式的基础上,添加了一些新的架构元素。mvc模式促使业务逻辑与界面分离,界面与控制行为分离,而refactoringwizard框架增强了界面本身分离的特性,它将一个完整的界面分拆成多个页面,用户可以动态组合这些页面或添加新的页面来扩展界面行为。这种特性-界面的动态组合,低耦合,高内聚,封装良好的接口-让我们领略到了oo设计的精髓。 下面我们通过以下几个步骤来扩展refactoringwizard框架: ?扩展refactoringwizardpage ?扩展refactoringwizard ?启动refactoringwizard 第一步,扩展refactoringwizardpage:首先我们新建一个类annotationrefactoringwizardpage,它需要继承userinputwizardpage类(其父类是refactoringwizardpage,而refactoringwizardpage最终实现了idialogpage接口)。接下来就是实现idialogpage接口的createcontrol(…)方法,在这个方法里实现你的界面行为,比如我们例子中的timeout文本框,代码清单如下: 清单 14 /** * create composite to add ui elements */ public void createcontrol(composite parent) { // define ui composite composite = new composite(parent, swt.none); gridlayout lay = new gridlayout(); lay.numcolumns = 2; composite.setlayout(lay); btncheck = new button(composite, swt.check); btncheck.settext("add timeout parameter"); griddata gdbtncheck = new griddata(); gdbtncheck.horizontalspan = 2; gdbtncheck.horizontalalignment = griddata.fill; btncheck.setlayoutdata(gdbtncheck); labname = new label(composite, swt.wrap); labname.settext("timeout:"); griddata gdlabname = new griddata(); gdlabname.horizontalalignment = griddata.beginning; gdlabname.grabexcesshorizontalspace = true; labname.setlayoutdata(gdlabname); txttimeout = new text(composite, swt.single | swt.border); griddata gdtxttimeout = new griddata(); gdtxttimeout.horizontalalignment = griddata.end; gdlabname.grabexcesshorizontalspace = true; txttimeout.setlayoutdata(gdtxttimeout); txttimeout.settext("500"); // init status labname.setenabled(false); txttimeout.setenabled(false); // add listener definelistener(); // 将composite纳入框架的控制 setcontrol(composite); dialog.applydialogfont(composite); } 在这里我们要特别注意的一点是在定义完我们的界面元素后,需要将自定义的composite纳入框架的控制,就是这行代码:"setcontrol(composite);" 在我们处理完输入数据检查后进入下一页面之前,我们需要设置页面完成的状态,以及传递输入数据到领域类refactoring。我们用以下代码设置好页面完成的状态后,下个页面errorwizardpage就会处理显示逻辑: 清单 15 private void notifystatus(boolean valid, string message) { //设置错误信息 seterrormessage(message); //设置页面完成状态 setpagecomplete(valid); } 传递输入数据通过以下代码来处理: 清单 16 private void setrefactoring(boolean selection, string text) { annotationrefactoring refactoring = (annotationrefactoring) getrefactoring(); refactoring.setneedtimeout(true); if(selection) { refactoring.settimeout(integer.valueof(txttimeout.gettext()).intvalue()); } } 其中getrefactoring()方法是继承自refactoringwizardpage的方法,由于我们的refactoringwizard类装载了refactoringwizardpage和refactoring类,这个方法是从refactoringwizard类中获得的,这里面用到了observer设计模式。至此,我们完成refactoringwizardpage的扩展。 第二步,扩展refactoringwizard:首先我们新建一个类annotationrefactoringwizard,它需要继承refactoringwizard类,这个类中我们只需要加载定义好的annotationrefactoringwizardpage类和annotationrefactoring类,当然复杂的处理已经有refactoringwizard框架处理好了。下面我们在构造函数中加载refactoring类: 清单 17 public annotationrefactoringwizard(refactoring refactoring) { super(refactoring, wizard_based_user_interface); } 然后我们加载我们的annotationrefactoringwizardpage类,只需重载父类refactoringwizard的adduserinputpages()方法就可以: 清单 18 protected void adduserinputpages() { page = new annotationrefactoringwizardpage("refactor annotation"); addpage(page); } 第三步,启动refactoringwizard。扩展好refactoringwizard之后,就需要在用户点击菜单项或是按钮时弹出这个对话框。refactoringwizard最好使用refactoringwizardopenoperation类来打开(当然也可以用refactoringwizarddialog)。refactoringwizardopenoperation首先进行重构的初始检查,通过后才打开refactoringwinzard对话框,否则就会打开错误对话框。前面完成创建插件工程时我们提到,弹出refactoringwizard对话框的代码应该放到响应菜单操作的类的run函数中。具体到本文工程中,就是把下面的代码放到annotationmanageaction的run函数中。这些代码首先依次构造refactoring和refacoringwizard子类annotationrefactoring和annotationrefactoringwizard,并将annotationrefactoring的引用传递给annotationrefactoringwizard,然后用refactoringwizardopenoperation打开annotationrefactoringwizard,弹出向导对话框。 清单 19 public void run(iaction action) { shell shell = window.getshell(); annotationrefactoring refactor = new annotationrefactoring(select); annotationrefactoringwizard wizard = new annotationrefactoringwizard(refactor); refactoringwizardopenoperation op = new refactoringwizardopenoperation(wizard); try { op.run(shell, "inserting @override annotation"); } catch (interruptedexception e) { e.printstacktrace(); } } 小结 在eclipse中有效的利用重构能够大大的减轻软件开发人员的工作负担,提高软件的健壮性。然而,目前重构仍然处在一个工具缺乏的时代。以eclipse为例,只有jdt提供的重构工具最为完善,而针对其他语言例如c++、python等的开发环境,都缺乏对应的重构功能。 通过本文提供的方法,我们能够有效的利用eclipse中的重构框架创建新的重构,从而进一步提高已有开发环境的效率。
|
|