由于腳本語言通常提供了更為簡(jiǎn)潔的語法及Java所不具有的一些新的語言特性(如:閉包,元編程等),所以在一些情況下可以創(chuàng)造出比Java程序更具有可讀性的代碼。另外,眾多基于JVM的腳本語言也為與Java程序整合帶來了便利。

Client: 語義模型實(shí)例的調(diào)用者
SemanticConcept: 語義模型定義,可以通過腳本語言或Java實(shí)現(xiàn)
ModelBuilder: 語義模型實(shí)例創(chuàng)建者,使用語義模型定義創(chuàng)建特定語義模型實(shí)例
相關(guān)基本概念可以參考:
DSL的實(shí)現(xiàn)要點(diǎn)(1)
以下還是以自動(dòng)門狀態(tài)機(jī)來作為實(shí)例:
語義概念定義:
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;
}
}
語義模型實(shí)例創(chuàng)建者
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,可見語言特性(集合及對(duì)象創(chuàng)建)有效提高了代碼的可讀性。
連接腳本語言與Java
作者采用Spring來實(shí)現(xiàn)Java及腳本語言的連接,你可以采用其他方式(如:JDK6的Script 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調(diào)用程序
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);
}
}
由于腳本語言是解釋執(zhí)行的,所以可以用作配置文件一樣,在部署后進(jìn)行修改。同時(shí)腳本語言本身所具有的強(qiáng)大語法可以使其很容易地完成普通配置很難完成的功能。所以在很多時(shí)候我們都應(yīng)該考慮使用腳本語言來進(jìn)行配置。