现在我们知道了XWorker是一个动态系统,事物可以转化为动作,动作是可以执行的。但是动作是怎样执行的呢?任何一个事物转化后的动作都能正确执行么?本文将回答这些问题。
如果一个动作的事物名是JavaAction,那么它就是基本动作,基本动作是由X-Meta引擎直接解释执行的。
如上图是一个JavaAction的示例,在这个模型里指定了Java的类全名和要执行的方法,这样X-Meta引擎就知道要找那个类执行那个方法了。
package xworker.swt.widgets; public class ShellCreator{ //X-Meta引擎能够调用的方法必须是静态方法,且参数固定为ActionContext public static Object create(ActionContext actionContext){ //相关代码 } }
如上面代码示例,X-Meta引擎调用静态的且参数必须是ActionContext的方法,如果JavaAction指定了合适的类和方法,那么X-Meta引擎就可以正确调用了。
在JavaAction的Java代码里我们看到方法的参数是ActionContext,ActionContext的名称叫做变量上下文(或动作上下文),它的主要作用是保存变量用的。
//变量上文的基本用法是保存变量和获取变量 //保存变量 actionContext.put("varName", varObject); //获取变量 Object varObject = actionContext.get('varName");
//变量上下文本身也是一个栈,栈中的每一个层是Bindings对象,Bindings可以保存变量 //压栈 Bindings bindings = actionContext.push(); //顶端的栈 Bindings bindings = actionContext.peek(); //出栈 Bindings bindings = actionContext.pop(); //使用Bindings设置变量和获取变量的值 bindings.put("varName", varObject); Object varObject = bindings.get("varName");
变量上下文是一个栈,从变量上下文取参数时是自上而下获取的,也就是说如果不同的栈层的Bindings包含同样的变量名,那么只会取到顶端第一个包含变量名的那个栈层的变量。
//压入第一个栈 Bindings bindings1 = actionContext.push(); bindings1.put("name", "tom"); //压入第二个栈 Bindings bindings2 = actionContext.push(); bindings2.put("name", "Smith"); //此时控制输出的是顶端栈中的Smith System.out.println(actionContext.get("name")); //弹出顶端的栈 actionContext.pop(); //此时控制台输出的tom System.out.println(actionContext.get("name"));
使用变量上下文是一个栈和取变量的自上而下的特性,可以在调用一个动作前压入一个栈,在这个栈中存放参数变量,从而实现传递参数的功能。
变量上下文的栈是ThreadLocal的,即每个线程拥有一个独立栈,因此变量上下文是线程安全的,变量上下的栈是由各自的线程维护的。
变量上下文的0层栈是每个线程都共有的,因此0层栈的变量相对来说是全局的,而非0层的栈则可以认为是局部的。
动作是可以执行的程序,可以在代码中调用动作。由于X-Meta引擎是使用Java编写的,所以可以在Java代码中调用动作。
//获取模型事物,其中World是管理事物的容器类,path是事物的路径 Thing thing = World.getInstance().getThing("path"); //转化为动作,任何事物都可以转化为动作 Action action = thing.getAction(); //创建变量上下文 ActionContext actionContext = new ActionContext(); //执行动作 action.run(actionContext);
在用对象的角度看待事物时,事物是具有行为的,调用事物行为的示例如下。
//获取模型事物,其中World是管理事物的容器类,path是事物的路径 Thing thing = World.getInstance().getThing("path"); //创建变量上下文 ActionContext actionContext = new ActionContext(); //执行事物的行为run thing.doAction("run", actionContext);
可以看到事物的行为是通过doAction方法调用的。
首先行为也是动作,只是一个动作被当成了某个对象的行为,其次行为是通过模型寻找到的某个子模型,最后在代表行为的子模型转化为动作执行前,最为对象的模型本身会以名为self的参数放到变量上下文中。
所以动作执行时没有self参数,而行为执行时是有self参数的,这里self变量类似Java的this变量的效果。
JavaAction是基本类型的动作,但JavaAction也有一点缺陷,那就是Java代码通常是模型之外东西,就算在JavaAction模型中直接写Java代码,那么也是很繁琐的。
基于以上原因,我们利用事物的行为来实现脚本动作或其它非JavaAction的动作。
首先在模型编程中动作本身也是模型,因此动作也可以当做对象来看待,如果把动作当做对象来看待,那么动作就具有行为,此时就可以把对象名为run的行为当成它的执行动作了。
这有点类似java.lang.Runnable这个类,动作是可以执行的,只要实现它的run方法就可以了。
如上图是GroovyAction的示例,在GroovyAction里脚本是直接写到代码里的。
通过实现事物的run方法,可以实现各种类型的动作,比如支持Jython、Lua等其他语言的动作,也比如Begin、If、while、for这样的控制语句的动作,也可以实现其它效果的动作。
Copyright © 2007-2014 XWorker.org 版权所有