J2EE之巅

 

DSL实现要点(3)--利用脚本语言实现DSL

 

由于脚本语言通常提供了更为简洁的语法及Java所不具有的一些新的语言特性(如:闭包,元编程等),所以在一些情况下可以创造出比Java程序更具有可读性的代码。另外,众多基于JVM的脚本语言也为与Java程序整合带来了便利。


Client: 语义模型实例的调用者

SemanticConcept: 语义模型定义,可以通过脚本语言或Java实现

ModelBuilder: 语义模型实例创建者,使用语义模型定义创建特定语义模型实例

相关基本概念可以参考:

DSL的实现要点(1)

以下还是以自动门状态机来作为实例:

语义概念定义:

Process.java

package org.ccsoft.statemachine;

import java.util.List;

publicclass Process {

      private String name;

      private List<State> states;

      public String getName() {

            returnname;

      }

      publicvoid setName(String name) {

            this.name = name;

      }

      public List<State> getStates() {

            returnstates;

      }

      publicvoid setStates(List<State> states) {

            this.states = states;

      }

      private State getStateByName(String name){

            for (State state:states){

                  if (state.getName().equals(name)){

                        return state;

                  }

            }

            returnnull;

      }

      public State transit(String curState,String event){

            for (State state:states){

                  if (state.getName().equals(curState)){

                        String nextS=state.getTransitions().get(event);

                        return getStateByName(nextS);

                  }

            }

            returnnull;

      }

}

State.java

package org.ccsoft.statemachine;

import java.util.Map;

publicclass State {

      private String name;

      /**Map<state,event>**/

      private Map<State,String> transitions;

      public String getName() {

            returnname;

      }

      publicvoid setName(String name) {

            this.name = name;

      }

      public Map<State, String> getTransitions() {

            returntransitions;

      }

      publicvoid setTransitions(Map<State, String> transitions) {

            this.transitions = transitions;

      }

      @Override

      publicboolean equals(Object obj) {

            if (obj instanceof State){

                  State other=(State)obj;

                  if (other.getName().equals(this.name)){

                        returntrue;

                  }

            }

            returnfalse;

      }

      @Override

      publicint hashCode() {

            // TODO Auto-generated method stub

            returnname.hashCode();

      }

      @Override

      public String toString() {

            // TODO Auto-generated method stub

            returnname;

      }

     

     

}

语义模型实例创建者

IStateMachineBuilder.java

package org.ccsoft.statemachine;

publicinterface IStateMachineBuilder {

      public Process build(String processName);

}

package org.ccsoft.statemachine

publicclass StateMachineBuilder implements IStateMachineBuilder{

       public Process build(String processName){

             

             switch(processName){

             case"service":

                  Process process =

                              new Process(

                                          states:[

                                             new State(

                                                      name:"open",

                                                      transitions:

                                                      [                            

                                                             "timeOut":"close",

                                                             "peopleClose":"close"

                                                      ]

                                                     

                                             ),

                                             new State(

                                                         name:"close",

                                                         transitions:

                                                            [                            

                                                                  "peopleOpen":"close"

                                                            ]

                                             )

                                          ]

                              );

                   return process;

                   default:

                         returnnull;

             }

       }   

}

作者采用的是Groovy,可见语言特性(集合及对象创建)有效提高了代码的可读性。

连接脚本语言与Java

作者采用Spring来实现Java及脚本语言的连接,你可以采用其他方式(如:JDK6Script Engine)。

Spring配置文件(stateMachine.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xmlns:lang="http://www.springframework.org/schema/lang"

      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

            http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">

      <lang:groovy id="stateMachineBuilder" script-source="file:src/org/ccsoft/statemachine/StateMachineBuilder.groovy">

      </lang:groovy>

     

</beans>

Java调用程序

package org.ccsoft.statemachine;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

publicclass Main {

      /**

       *@paramargs

       */

      publicstaticvoid main(String[] args) {

            ApplicationContext ctx = new ClassPathXmlApplicationContext("stateMachine.xml");

            IStateMachineBuilder builder=(IStateMachineBuilder) ctx.getBean("stateMachineBuilder");

            Process process=builder.build("service");

            State nextState = process.transit("open", "timeOut");

            System.out.println(nextState);

      }

}

由于脚本语言是解释执行的,所以可以用作配置文件一样,在部署后进行修改。同时脚本语言本身所具有的强大语法可以使其很容易地完成普通配置很难完成的功能。所以在很多时候我们都应该考虑使用脚本语言来进行配置。

posted on 2010-04-06 18:21 超越巅峰 阅读(3659) 评论(0)  编辑  收藏 所属分类: DSL


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(12)

随笔分类(54)

随笔档案(59)

文章分类(2)

文章档案(1)

相册

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜