扩展RefactoringWizard 框架
Eclipse中的RefactoringWizard框架扩展了Eclipse的Wizard框架关于Wizard框架的介绍可以在Eclipse的帮助系统中找到这里我们仅从OO设计和架构的角度探讨一下RefactoringWizard框架
我们从Wizard相关的几个类开始
WizardPage类
WizardPage是一个包含了多个界面元素(比如文本框Text按钮Button)的一个界面组合部分各个Page之间是独立的是可以动态加载的WizardPage类的职责有
·组合SWT界面元素构造出一个界面页
·定义本身界面元素的操作行为
在RefactoringWizard框架中预设了两个通用的属性页PreviewWizardPage和ErrorWizardPagePreviewWizardPage类是用来预览重构后的修改对比代码或其他资源的变化ErrorWizardPage类是用来处理条件检查及错误状态通知的我们只需扩展RefactoringWizard框架就可以自动获取这两项强大的功能
Wizard类
一个Wizard就是一个装载一系列WizardPage页的容器Wizard类的职责有
·装载一系列WizardPage构造出一个复杂的界面
·装载领域类来处理具体业务逻辑(在RefactoringWizard框架中这个类就是Refactoring类)
维护WizardPage页之间以及页与领域类之间的数据传递和状态共享(在这里要补充一点其实在具体RefactoringWizard框架的实现中有专门的类来分担这部分职责)
我们的界面行为可以千变万化(通过组合不同的WizardPage)而负责处理业务逻辑的领域类也可以独立的变化你可以随意扩展Wizard的界面功能(-对扩展开放)而不用修改现有RefactoringWizard框架(-对修改封闭)这正是OO设计的最基本原则-OCP(OpenClose Principle)
WizardDialog类
这个对话框类的主要职责是构造一个完整的GUI界面以及操作界面它预设了一些按钮(BackNextFinishCancel)等界面元素它负责装载Wizard类操作时通过按钮BackNext来在多个WizardPage之间切换
下面我们给出RefactoringWizard框架的架构图
图 Refactoring Wizard架构图
从图 中我们可以看到如果我们把每一个WizardPage页看作一项业务那么Refactoring正是处理业务逻辑的控制中心它封装了所有对业务逻辑的处理当然它可以在将处理任务委任出去但请注意它并不负责实现业务流程也就是说各业务(各个Page界面)之间的逻辑顺序关系不由它维护
RefactoringWizard框架充分考虑到了应用的可扩展性它在SWT的MVC(模型-视图-控制)元架构模式的基础上添加了一些新的架构元素MVC模式促使业务逻辑与界面分离界面与控制行为分离而RefactoringWizard框架增强了界面本身分离的特性它将一个完整的界面分拆成多个页面用户可以动态组合这些页面或添加新的页面来扩展界面行为这种特性-界面的动态组合低耦合高内聚封装良好的接口-让我们领略到了OO设计的精髓
下面我们通过以下几个步骤来扩展RefactoringWizard框架
·扩展RefactoringWizardPage
·扩展RefactoringWizard
·启动RefactoringWizard
第一步扩展RefactoringWizardPage首先我们新建一个类AnnotationRefactoringWizardPage它需要继承UserInputWizardPage类(其父类是RefactoringWizardPage而RefactoringWizardPage最终实现了IDialogPage接口)接下来就是实现IDialogPage接口的createControl(…)方法在这个方法里实现你的界面行为比如我们例子中的TimeOut文本框代码清单如下
清单
/**
* create composite to add UI elements
*/
public void createControl(Composite parent) {
// define UI
Composite composite = new Composite(parent SWTNONE);
GridLayout lay = new GridLayout();
laynumColumns = ;
compositesetLayout(lay);
btnCheck = new Button(composite SWTCHECK);
btnChecksetText(Add timeout parameter);
GridData gdBtnCheck = new GridData();
gdBtnCheckhorizontalSpan = ;
gdBtnCheckhorizontalAlignment = GridDataFILL;
btnChecksetLayoutData(gdBtnCheck);
labName = new Label(composite SWTWRAP);
labNamesetText(TimeOut:);
GridData gdLabName = new GridData();
gdLabNamehorizontalAlignment = GridDataBEGINNING;
gdLabNamegrabExcessHorizontalSpace = true;
labNamesetLayoutData(gdLabName);
txtTimeOut = new Text(composite SWTSINGLE | SWTBORDER);
GridData gdTxtTimeOut = new GridData();
gdTxtTimeOuthorizontalAlignment = GridDataEND;
gdLabNamegrabExcessHorizontalSpace = true;
txtTimeOutsetLayoutData(gdTxtTimeOut);
txtTimeOutsetText();
// init status
labNamesetEnabled(false);
txtTimeOutsetEnabled(false);
// add listener
defineListener();
// 将composite纳入框架的控制
setControl(composite);
DialogapplyDialogFont(composite);
}
在这里我们要特别注意的一点是在定义完我们的界面元素后需要将自定义的Composite纳入框架的控制就是这行代码setControl(composite);
在我们处理完输入数据检查后进入下一页面之前我们需要设置页面完成的状态以及传递输入数据到领域类Refactoring我们用以下代码设置好页面完成的状态后下个页面ErrorWizardPage就会处理显示逻辑
清单
private void notifyStatus(boolean valid String message) {
//设置错误信息
setErrorMessage(message);
//设置页面完成状态
setPageComplete(valid);
}
传递输入数据通过以下代码来处理
清单
private void setRefactoring(boolean selection String text) {
AnnotationRefactoring refactoring = (AnnotationRefactoring) getRefactoring();
refactoringsetNeedTimeout(true);
if(selection) {
refactoringsetTimeout(IntegervalueOf(txtTimeOutgetText())intValue());
}
}
其中getRefactoring()方法是继承自RefactoringWizardPage的方法由于我们的RefactoringWizard类装载了RefactoringWizardPage和Refactoring类这个方法是从RefactoringWizard类中获得的这里面用到了Observer设计模式至此我们完成RefactoringWizardPage的扩展
第二步扩展RefactoringWizard首先我们新建一个类AnnotationRefactoringWizard它需要继承RefactoringWizard类这个类中我们只需要加载定义好的AnnotationRefactoringWizardPage类和AnnotationRefactoring类当然复杂的处理已经有RefactoringWizard框架处理好了下面我们在构造函数中加载Refactoring类
清单
public AnnotationRefactoringWizard(Refactoring refactoring) {
super(refactoring WIZARD_BASED_USER_INTERFACE);
}
然后我们加载我们的AnnotationRefactoringWizardPage类只需重载父类RefactoringWizard的addUserInputPages()方法就可以
清单
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弹出向导对话框
清单
public void run(IAction action) {
Shell shell = windowgetShell();
AnnotationRefactoring refactor = new AnnotationRefactoring(select);
AnnotationRefactoringWizard wizard = new AnnotationRefactoringWizard(refactor);
RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
try {
oprun(shell Inserting @Override Annotation);
} catch (InterruptedException e) {
eprintStackTrace();
}
}
小结
在Eclipse中有效的利用重构能够大大的减轻软件开发人员的工作负担提高软件的健壮性然而目前重构仍然处在一个工具缺乏的时代以Eclipse为例只有JDT提供的重构工具最为完善而针对其他语言例如C++Python等的开发环境都缺乏对应的重构功能 通过本文提供的方法我们能够有效的利用Eclipse中的重构框架创建新的重构从而进一步提高已有开发环境的效率