【软件构造】基于正则表达式匹配创建自定义对象

问题:

我们在构造 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));//证明两种构造方法的等价性
}

结果没有问题: 另外,可以使用多个不同的正则表达式以匹配用户的不同输入,增加构造对象的灵活性

经验分享 程序员 微信小程序 职场和发展