作者LaPass (LaPass)
看板java
标题Re: [问题] 如何弹性不修改程式码, 却能比对模式
时间Sat Nov 30 23:42:16 2013
※ 引述《smithkimo (Smith K)》之铭言:
: Dear all,
: 小弟有一个很特别的问题, 就是手边有一些会随时会增加的规则,
: 例如,
: String test = "abc";
: Rule 1: if(regex1.match()) then ...
: Rule 2: if(regex2.match()) then ...
: 这些规则会随时增加, 但是比对的逻辑是透过if...else if...else if...
: 如果一增加rules, 就必须要修改判断的主程式, 新增新的else if的判断,
: 不知道有办法, 不更动判断的程式, 但却可以任意增加rules呢
: 想设计一个较弹性的判断程式, 谢谢大家
其实这比较像是设计概念的问题
一些实行的细节我会略过
程式码也没跑过,就是示意一下怎麽设计这样
在你的例子中
你的要求是弹性的进行比对
以及对比对成功的动作进行不同的动作
所以,在这里我们要作的
是将「比对条件」以及「执行动作」这两个部份
从主结构中抽离出来
也就说,不要用if....else的写法
在这里,来复习一下物件导向的概念
一个物件可以是一个「东西」当然也可以是「条件」或是「执行动作」
所以,你可以定一个界面以及物件像这样:
interface IRegexAction
{
//检查字串有没有合乎条件
//data为判断的字串
boolean check(String data);
//处理的动作
//data为判断的字串
//return 为处理後的字串
String invoke(String data);
}
然後,你可以宣告一个List去放这个条件跟执行动作的配对
List<IRegexAction> regexActions=new ArrayList<>();
然後把你的条件放进去
regexActions.add(new CheckEmpty()); //假设这个把空白去除
regexActions.add(new Replace("o","O")); //假设这是把o变成O
之後,逐一检查你的条件
String data="Hello World!"; //这是要需要判断的资料
for(IRegexAction regexAction : regexActions)
{
if(regexAction.check(data))
{
data=regexAction.invoke(data);
//假设你原本用的是用的是if.....else if.... else if....
//就在这里加个break
//如果是 if....; if....; 就不用加break
break;
}
}
到目前为止是第一阶段
请先看懂这部份
这是教你怎麽把一般的if...else之类的简单程式流程,换成List去跑
这是比较简单的部份
============================================
第一阶段的那个方法
虽然可以作到把「条件」、「执行动作」从主逻辑中抽出
但是你看看下面这一段
regexActions.add(new CheckEmpty()); //假设这个把空白去除
regexActions.add(new Replace("o","O")); //假设这是把o变成O
虽然要加新的判断条件时,只需宣告一个物件,实作IRegexAction
但还是需要到主程式中加入那一行 regexActions.add(...); 的程式片段
这里要讲的,是把你的「条件」以及「动作」放到档案中
因为你讲的
Rule 1: if(
条件) then
动作
条件这部份,处理起来还颇简单的,因为regex就是表示式而已
可以把表示式放到档案中没问题
但是动作这部份比较麻烦
java中没有像php或是ruby, JavaScript之类的evel可以跑程式码
所以,处理起来会比较麻烦就是了
在这里,至少有三种方法可以解决掉这个问题
1.是自定义档案中的动作名称,例如在档案中的动作是这样
"shoutdown(\snow)+" shoutdown
前面这一段是表示式,把这段字串塞进Pattern里面就是了
第二段,基本上就是判断一下读到的字串是什麽动作,就去执行什麽动作这样
基本上还是用第一阶段的方法去做
如果是小东西的话,用这个方法就足够了
2.用Reflection
JAVA有个功能,可以动态载入class
你可以看看Reflection那部份
然後用个档案纪录class的名称,他长的应该像是
com.ptt.myclass.Action
com.ptt.myclass.Action2
之类的
读到这个名称之後,靠Reflection就可以去建立实体
我比较喜欢用这个方法,因为用起会比较方便
3.自己写个解释器去处理
简单来讲.... 就是自订一套脚本的处理方式
一般是只有framework等级的程式才会这样干
只不过写起来也不难
去google一下lua java或是javascript java engine
应该就能找到很多资料
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.38.71.182
1F:推 popcorny:认真就给推! 12/02 08:11
2F:推 qrtt1:有看有推,不过原 PO 好像跑去 codejob 发案了xd 12/02 09:49
3F:→ LaPass:他一开始就在那边发案的啊... 大概是想要看Demo XD 12/02 10:12