在JavaScript中实现复杂的决策表

时间:2011-01-12 21:29:57

标签: javascript

这是JavaScript专家的实现细节问题。

我有一个包含许多字段的UI,其中字段的值以七位输入的值复杂地依赖。当用户看到更多应用程序时,应该显示哪些可能的128个值会定期更改?

现在,我已经通过if-then-else梳子将其作为决策树来实现,但是在需求变化下它很脆弱,而且很难做到正确。

我想到的一种实现方法是创建一个从0x0到0x7F的值数组,然后在每个位置存储一个闭包 -

var tbl; // initialize it with the values
  ...
tbl[0x42] = function (){ doAThing(); doAnotherThing(); }

然后使用

调用它们
tbl[bitsIn]();

这至少使决策逻辑成为一堆任务。

问题:有更好的方法吗?

(更新:神圣的废话,关于'ajax iphone标签'的那条线怎么进入那里?难怪它有点令人费解。)

更新

那发生了什么?基本上我采取了第四种选择,虽然类似于我检查过的那种。逻辑非常复杂,我最终构建了一个Python程序来生成服务器中的真值表(生成Groovy代码,实际上,主机是Grails应用程序)并将决策逻辑移入服务器完全。现在,JavaScript方面只是解释一个包含各个字段值的JSON对象。

最终,这可能会再经历一次迭代,并成为数据库表中的数据,由位向量索引。

表驱动部分肯定是出路;在显示的具体要求中已经有六个新的更改。

4 个答案:

答案 0 :(得分:5)

我看到两个选项......

两种解决方案的共同点是以下命名函数:

function aThing() {}
function anotherThing() {}
function aThirdThing() {}

切换方式

function exec(bits) {
 switch(bits) {
    case 0x00: aThing(); anotherThing(); break;
    case 0x01: aThing(); anotherThing(); aThirdThing(); break;
    case 0x02: aThing(); aThirdThing(); break;
    case 0x03: anotherThing(); aThirdThing(); break;
    ...
    case 0x42: aThirdThing(); break;
    ...
    case 0x7f: ... break;
    default: throw 'There is only 128 options :P';
  }
}

地图方式

function exec(bits) { 
    var actions = map[bits];
    for(var i=0, action; action=actions[i]; i++)
        action(); 
}

var map = {
 0x00: [aThing, anotherThing],
 0x01: [aThing, anotherThing, aThirdThing],
 0x02: [aThing, aThirdThing],
 0x03: [anotherThing, aThirdThing],
    ...
 0x42: [aThirdThing],
    ...
};

在这两种情况下你都会打电话

exec(0x42);

答案 1 :(得分:2)

由于情况(正如您所描述的)是如此不规则,似乎没有更好的方法。虽然,我可以建议你的跳转表改进。您提到您有错误和重复。因此,您可以将它们分配给命名函数,而不是显式地将它们分配给闭包,这样您就不必复制显式闭包。

var doAThingAndAnother = function (){ doAThing(); doAnotherThing(); }

var tbl; // initialize it with the values
  ...
tbl[0x42] = doAThingAndAnother;
tbl[0x43] = doAThingAndAnother;

没有那么大的改进,但这是我唯一能想到的!你似乎已经涵盖了大多数其他问题。由于看起来需求变化如此之大,我认为你可能不得不放弃优雅,并且设计不那么优雅,但仍然很容易改变。

答案 2 :(得分:1)

您是否考虑过在服务器上生成决策树而不是手工编写?使用任何表示干净,易于使用,并修改,然后编译为客户端丑陋但有效的JavaScript。

决策树很容易表示为数据,并且易于理解并与传统的树数据结构一起使用。您可以以任何对您有意义的形式存储所述树。验证和修改数据也应该是直接的。

然后,当您需要使用决策树时,只需将其编译/序列化为JavaScript,作为一个大的if-the-else,switch或hash mess。这也应该是相当直接的,并且可能比尝试维护具有几百个元素的switch容易得多。

答案 3 :(得分:1)

如果你想看看,我有一个JavaScript决策树工具的粗略示例:

http://jsfiddle.net/danw/h8CFe/