0

假设我想编写动态代码:

魔兽争霸3触发系统:

Event: if a unit levels
  Condition: if ( triggeringUnit is alive ) && ( triggeringUnit.name="something" )

爪哇

for ( Unit triggeringUnit : leveledUnits )
{
  condition1 = new IsAliveCondition(triggeringUnit);
  condition2 = new HasNameCondition(triggeringUnit);
  if ( new AndCondition( condition1 , condition2 ).isTrue() )
  {

  }
}

问题: 如果代码是静态编写的,则此代码运行,但它不能动态形成。条件 1,2 在其构造函数中需要一个“特定单元”才能被创建,因此它们不可能存储在内存中(因为它们无法被创建)。存在此问题的原因是:条件 1,2 不知道它将位于“for-loop”内,也不知道该范围内没有变量“triggeringUnit”。

为了解决这个问题,我应该创建一个包含范围内所有变量的哈希图吗?


Hashmap<String, Object> variables = ... ;
   condition1 = new IsAliveCondition("triggeringUnit");
   condition2 = new HasNameCondition("triggeringUnit");
   condition = new AndCondition( condition1, condition2);

   //At Runtime
   for( Unit triggeringUnit : leveledUnits )
   {
      variables.put("triggeringUnit", triggeringUnit );
      if ( condition.isTrue() )
      {

      }
   }


有没有更好的解决方案/设计模式?

4

3 回答 3

0

看起来有点像您正在寻找Business Rules Systems。这些系统允许使用 GUI 或某种脚本来制定规则,并且可以与语言(通常是 java)进行交互,以便为规则提供更多功能并让程序调用规则引擎。

最著名的免费和开源 BRMS 是DROOLS

于 2012-09-13T11:38:51.660 回答
0

通常这需要一些发布/订阅机制,或者GOF 所称的观察者模式。创建事件类型层次结构并在发生任何事情时触发事件,让观察者订阅支持的事件。

这是一个初步的初稿:

interface EventListener<X extends EventType>{
    processEvent(Map<String, Object> data);
}

public class EventDispatcher{
    private Map<EventType, Collection<EventListener<?>> listeners; // initialize this
    public <X extends EventType> void addListener(X type, EventListener<X> listener){
        // add listener to map
    }
    public void dispatchEvent(EventType type, Map<String, Object> data){
        if(listeners.containsKey(type){
            for(EventListener<EventType> listener: listeners.get(type)){
                listener.processEvent(data);
            }
        }
    }
}

现在,当升级事件发生时,您的数据地图将包含升级单位的存活和名称统计信息。

于 2012-09-13T12:05:03.550 回答
0

对于动态条件,您可以使用动态语言。下面是 Groovy 中的代码片段,可以在 Groovy 控制台中运行。

class IsAliveCondition {
    def triggeringUnit

    boolean isCase() {
        triggeringUnit.alive
    }
}

class HasNameCondition {
    def triggeringUnit
    def name

    boolean isCase() {
        triggeringUnit.name == name
    }
}

class MyUnit {
    def alive
    def name
}

def condition = '''
new IsAliveCondition(triggeringUnit: triggeringUnit) && 
new HasNameCondition(triggeringUnit: triggeringUnit, name: 'somename').isCase()
'''

def leveledUnits = [new MyUnit(alive: true, name: 'somename'), new MyUnit(name: 'Joe')]

leveledUnits.each { triggeringUnit ->
    def shell = new GroovyShell(this.class.classLoader, new Binding([triggeringUnit: triggeringUnit]))
    if (shell.evaluate(condition)) {
        println "Condition for <$triggeringUnit.name> satisfied: $condition"
    }
}

你看,这里的条件只是硬编码的字符串。但它可以很容易地从文件中读取。Binding是您使用过的一种哈希映射,但它是由 Groovy 提供的。

当然,JVM 还有很多其他的动态语言:Jython、JRuby、JavaScript 是主要的。它们通常与 Java 交互比较简单。例如,IsAliveConditionHasNameCondition可以用 Java 编写(在这种情况下,它们需要构造函数和 getter/setter 以及类型信息)。

于 2012-09-13T14:11:34.430 回答