现在我们知道了动态模型可以用XML这样的数据表示对象,它也实现了面向对象的方法,那么它能够实现的原理是什么呢?答案就是如何把模型解释为程序的方法,即模型本身是数据,现在我们要把数据当作程序来执行。
XWorker把Eclipse的开源组件SWT模型化了,我们用SWT的模型示例来说明。
模型是由属性和子节点构成的,它和XML的结构一样,可以转化为XML,所以我们一般用XML来展示模型,如下图:

这是一个SWT的窗口(Shell)的例子,其中根节点的descriptors属性指向的是它的描述者(类),xworker.swt.widgets.Shell也是一个模型,在这里作为示例模型的描述者(类)。在这个窗口示例中加入了一个Browser控件,用于显示XWorker的网站。
在上面的模型代码中并没有行为的定义,这是因为xworker.swt.widgets.Shell模型定义了相关的行为,它分别定义了create和run两个主要方法,通过执行run方法可以运行模型,运行后的截图如下。

上面展示了模型的代码和运行后的截图,下面我们详细说明这个模型是如何运行的。

上图是HelloWorld模型的编辑界面,可以看到HelloWorld的描述者即它的类是xworker.swt.widgets.Shell。

上图是Shell模型的编辑界面,可以看到hell模型使用JavaAction模型定义了run方法。
public static void run(ActionContext actionContext){
//self是模型本身
Thing self = (Thing) actionContext.get("self");
//调用模型自己的create方法构造Shell对象
Shell shel = (Shell) self.doAction("create", actionContext);
//运行Shell对象
Display display = shell.getDisplay();
while (!shell.isDisposed ()) {
try{
if (!display.readAndDispatch ()) display.sleep ();
}catch(Exception e){
e.printStackTrace();
}
}
display.dispose ();
}
如上面的示意代码,在Shell的run方法里首先通过变量上下文(ActionContext)获取模型本身,然后通过执行模型的create方法构建Shell对象,最后执行打开Shell窗口。
在上面的代码中Shell模型调用了自己的create方法,下面是create方法示意代码,这里截取了源码中的一些主要部分。
public class ShellCreator {
public static Object create(ActionContext actionContext){
World world = World.getInstance();
//self是事物模型本身
Thing self = (Thing) actionContext.get("self");
//初始化style,根据模型的属性初始化style
Action styleAction = world.getAction("xworker.swt.widgets.Composite/@scripts/@getStyles");
int style = (Integer) styleAction.run(actionContext);
//创建shell对象
Shell shell = null;
try{
Object parent = actionContext.get("parent");
if(parent instanceof Display){
shell = new Shell((Display) parent, style);
}else if(parent instanceof Shell){
shell = new Shell((Shell) parent, style);
}else{
Display display = Display.getCurrent();
if(display != null){
shell = new Shell(display, style);
}else{
shell = new Shell(style);
}
}
}catch(Exception e){
shell = new Shell(style);
}
//保存变量
actionContext.getScope(0).put(self.getString("name"), shell);
//创建子节点
actionContext.peek().put("parent", shell);
for(Thing child : self.getAllChilds()){
child.doAction("create", actionContext);
}
actionContext.peek().remove("parent");
return shell;
}
}
可以看到在这里同样是通过变量上下文ActionContext获取模型本身,然后通过模型创建相对应的Shell的Java对象,然后把它放到变量上下文中,然后是依次执行子节点的create方法,这样可以创建子节点的Java方法,最后返回Shell对象。

如上图在XWorker中约定每一个SWT模型都有一个create方法,这样通过执行create方法可以创建相对应的Java对象。
最后我们模型执行的流程梳理一遍。
通过上面的SWT模型的示例,我们可以发现这其实也是一种框架编程的方法,在这里模型可以看作是框架的配置文件,而Java代码是模型的解释引擎。
Copyright © 2007-2019 XWorker.org 版权所有 沪ICP备08000575号