【软件构造】基于正则表达式匹配创建自定义对象
问题:
我们在构造 java中一些较为复杂的自定义对象时,往往会遇到构造过程过于麻烦的问题,例如: 当一个对象的输入参数是Map时,需要用户先构造一个Map,再调用构造方法,这个过程过于繁琐。
解决方案:
使构造函数的参数为一个符合特定的语法规则的字符串,并使用java的正则表达式检测用户输入的字符串是否符合该语法规则,最后将输入的字符串解析为特定的参数对象即可。这样可以简化用户构造对象时的繁琐步骤。
正则表达式介绍:
正则表达式是一个字符串,使用单个字符串来描述、用来定义匹配规则,匹配一系列符合某个句法规则的字符串。在开发中,正则表达式通常被用来检索、替换那些符合某个规则的文本。 正则表达式的详细规则略。
例:
原构造方法传入一个Map对象:
private Map<String, Integer> options = new HashMap<>();
public VoteType(Map<String, Integer> options1) {
this.options.putAll(options1);
checkRep();
// TODO
}
更改为:
public VoteType(String regex) throws IllegalArgumentException{
String regexType="(\([A-Za-z0-9]+,\d+\))+";
if(!regex.matches(regexType))
throw new IllegalArgumentException("输入须符合特定语法");
StringBuilder sb=new StringBuilder(regex);
String ts=null;
int tv=0;
while(sb.length()>0) {
ts=sb.substring(1, sb.indexOf(","));
sb.delete(0,sb.indexOf(",")+1);
tv=Integer.valueOf(sb.substring(0, sb.indexOf(")")));
options.put(ts, tv);
sb.delete(0, sb.indexOf(")")+1);
}
}
详解:
1.匹配
String regexType="(\([A-Za-z0-9]+,\d+\))+"用于匹配特定语法规则的字符串,表示规则:
"({Option},{Value})"表示一个键值对,其中Option和它对应的权值,Option只包含字母和数字,权值必须是整数。
输入参数应是多个键值对的重复,如:“(like,1)(dislike,-1)”
以此匹配用户的输入,若不符合语法抛出异常。
2.处理:
使用StringBuilder可变的字符串处理输入,使用while循环每次处理一个键值对,流程:1.使用Integer.valueOf()等得到待处理的Key和value并加入原对象的私有Map字段。2.将已处理的"({Option},{Value})"删除,便于下次循环处理。3.直到该StringBuilder为空则结束
3.测试和验证:
使用Junit单元测试模块进行测试。
@Test
public void test() {
Map<String, Integer> options = new HashMap<>();
options.put("aa", 1);
options.put("bb", 2);
options.put("cc", 3);
VoteType tesType1 =new VoteType(options);//一般的构造
try {//测试不符合语法的输入
VoteType tesType =new VoteType("(aa,1),(bb,2)(cc,3)");
fail();
}catch (IllegalArgumentException e) {
System.out.println(e);
}
VoteType tesType =new VoteType("(aa,1)(bb,2)(cc,3)");//正则表达式的构造
assertTrue(tesType.equals(tesType1));//证明两种构造方法的等价性
}
结果没有问题: 另外,可以使用多个不同的正则表达式以匹配用户的不同输入,增加构造对象的灵活性
