动态模型的原理

    现在我们知道了动态模型可以用XML这样的数据表示对象,它也实现了面向对象的方法,那么它能够实现的原理是什么呢?答案就是如何把模型解释为程序的方法,即模型本身是数据,现在我们要把数据当作程序来执行。    

SWT模型示例

    XWorker把Eclipse的开源组件SWT模型化了,我们用SWT的模型示例来说明。

1.模型代码

    模型是由属性和子节点构成的,它和XML的结构一样,可以转化为XML,所以我们一般用XML来展示模型,如下图:

这是一个SWT的窗口(Shell)的例子,其中根节点的descriptors属性指向的是它的描述者(类),xworker.swt.widgets.Shell也是一个模型,在这里作为示例模型的描述者(类)。在这个窗口示例中加入了一个Browser控件,用于显示XWorker的网站。

2.运行模型

    在上面的模型代码中并没有行为的定义,这是因为xworker.swt.widgets.Shell模型定义了相关的行为,它分别定义了create和run两个主要方法,通过执行run方法可以运行模型,运行后的截图如下。

执行模型的方法详细说明    

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

1.HelloWorld的描述者是Shell

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

2.Shell模型的run方法

shellexample

    上图是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窗口。

3.create方法

    在上面的代码中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对象。

4.SWT模型的create方法

    如上图在XWorker中约定每一个SWT模型都有一个create方法,这样通过执行create方法可以创建相对应的Java对象。

5.流程梳理

    最后我们模型执行的流程梳理一遍。

  1. 通过执行HellWorld模型的run方法执行HelloWorld模型。
  2. HelloWorld模型的run方法继承于它的描述者即xworker.swt.widgets.Shell模型,执行Shell模型的run方法。
  3. Shell模型run方法使用JavaAction模型编写的,它对应于Java代码。
  4. 在run方法的Java代码中可以调用模型,在这里模型是方法的调用者HelloWorld模型,我们还可以执行模型的create方法。
  5. SWT模型的create方法是根据模型创建Java对象的方法。
  6. 最后在Shell的run方法里,通过self变量获取HelloWorld模型,通过执行它的create方法创建Shell对象,然后打开Shell(窗口),这样HelloWorld模型就执行了。

框架编程

    通过上面的SWT模型的示例,我们可以发现这其实也是一种框架编程的方法,在这里模型可以看作是框架的配置文件,而Java代码是模型的解释引擎。

Copyright ©  2007-2014 XWorker.org  版权所有

沪ICP备08000575号