表格驱动编程在代码中的应用

mac2022-06-30  86

1. 毕业设计中的使用

第一次使用表格驱动编程,是在大学毕业设计的时候。做一个LL(1)的词法分析程序,需要读取终结符、非终结符、以及推导公式。程序会根据以上信息生成FIRST集合和LAST集合,然后根据递归下降分析的方法,就可以判断当前的表达式,是否符合对应的文法规则了。因为在代码中对于推导用到的表格没有写为Hard Code(写死,硬编码),所以可以适应很多的符合规则的文法。

2. 开源代码中的使用

第二次遇到表格驱动编程的方法,是在LXGJ,做jpg图像的压缩,用的是jpeg2000。当时还写了一篇文章,总结了一下,具体见 http://www.cnblogs.com/Dennis-mi/p/3871860.html 。这里的代码采用的是动态生成表格的方式,在函数中通过宏来控制表格的大小,来实现动态的支持不同图片格式的解析。

3. 工作中使用

在LXGJ的时候,领导布置了一个任务,需要用户选择从不同的来源生成PDF,大致有扫描、文件、图片……,需要做成一个类似于Eclipse(Visual Studio)生成工程的向导类似的。然后明白了需求以后,我就开始写代码了。然后项目经理过来问我做的怎么样了,我把写了好多 if else的代码拿给他看,他说“你怎么能这么写呢,万一需求有变化,怎么改。

代码类似于

if( SCAN == type ) { dlg = new ScanDialog(); dlg.show(); if(DPI300 == dlg.getDpi()) { ..... } } else if(FILE == type) { ... } else if(IMAGE == type) { .... }

以上的代码在遇到规则有变化,或者每一步方式的选项要增加或者减少的时候,修改比较麻烦。 项目经理的建议

Dialog choiceDialog[4][5]= { new ScanDialog(),new DpiDialog(),new xxDialog(),NULL, new FileDialog(),new xxDialog(),NULL,NULL, new ImageDialog(),new DpiDialog(),new ImageTypeDialog(),new xxDialog(),NULL, NULL,NULL,NULL,NULL,NULL, }

采用下面的这种写法具有更好的可扩展性和灵活性。如果需要增加一种方式,则可以增加一行,如果需要增加方式中的一个选项,则可以在某行的某列后面增加一个dialog,用NULL表示结束,可以每种方式经过的选项不同。

4.我的新发现

在LXSJ的时候,我们需要对APP登录做验证,验证的过程比较多而且规则有可能会变化。这个时候采用表格驱动编程是一种很好的方式。举例说明如下: 比如我们需要验证

1、用户是否余额--->有余额允许登录,没有不允许; 2、用户是否是VIP会员--->是会员允许登录,不管其他条件; 3、用户如果是合作方的用户--->则合作方决定是否允许登录; 4、用户如果已经是老用户--->是允许登录,不是不允许登录;

此时可以采用老办法,用if else来写。但是新的方法是采用表格驱动,具体如下。 表格的每一项对应一个判断函数,返回 bool 值。

loginLogicTable[][] = { /*当前需要进行的判断,成功时的状态,失败时的状态*/ LOGIN_START,IS_VIP,IS_VIP, IS_VIP,LOGIN_SUCCEED,HAS_BALANCE, HAS_BALANCE,LOGIN_SUCCEED,IS_REGULAR_CUSTOMER, IS_REGULAR_CUSTOMER,LOGIN_SUCEED,IS_PARTER_CUSTOMER, IS_PARTER_CUSTOMER,SEND_REQUEST_TO_PARTER,LOGIN_FAILED, RECIVE_PARTER_RESPONSE,LOGIN_SUCCEED,LOGIN_FAILED, }

以上是此时规则的描述,其中 LOGIN_SUCCEED 与 LOGIN_FAILED 是最终的状态。 第一项对应着一个函数,使用这个表格的伪代码如下

bool isLoginSucceed(userInfo) { curState = LOGIN_START; while( curState != LOGIN_SUCCEED && curState != LOGIN_FAILED) { changeArray = findArray(curState); //返回loginLoginTable中的一行 if(callFunc(changeArray[0]) { curState=changeArray[1]; } else { curState = changeArray[2]; } } return curState == LOGIN_SUCCEED; }

如果不需要判断是否是合作伙伴的用户了。 则将

IS_REGULAR_CUSTOMER,LOGIN_SUCEED,[IS_PARTER_CUSTOMER], //改为 IS_REGULAR_CUSTOMER,LOGIN_SUCEED,[LOGIN_FAILED],

就可以了,改动非常的方便。 如果要增加一个判断,比如要增加xyz指令判断。 则修改如下:

IS_REGULAR_CUSTOMER,[LOGIN_SUCEED],IS_PARTER_CUSTOMER, IS_PARTER_CUSTOMER,SEND_REQUEST_TO_PARTER,LOGIN_FAILED, RECIVE_PARTER_RESPONSE,LOGIN_SUCCEED,LOGIN_FAILED, /*改为*/ IS_REGULAR_CUSTOMER,[JUDGE_XYZ_CMD],IS_PARTER_CUSTOMER, IS_PARTER_CUSTOMER,SEND_REQUEST_TO_PARTER,LOGIN_FAILED, RECIVE_PARTER_RESPONSE,[JUDGE_XYZ_CMD],LOGIN_FAILED, [JUDGE_XYZ_CMD],LOGIN_SUCCEED,LOGIN_FAILED,

可以看出,此时的修改很小,而且逻辑很清楚。

转载于:https://www.cnblogs.com/Dennis-mi/p/8612698.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)