现在我们知道了动态模型可以用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-2014 XWorker.org 版权所有