昨天看了@Brin想写程序 的文章 几行Java代码实现的简单模板(不是引擎),呵呵,就非常想去掏掏偶滴小兜兜,果然发现一个类似的东西,因为东西太小,没有准备怎么写,但是看到@Brin想写程序的文章,就想着也发篇文章,说一下当时我的想法与思路。
格式化提供者,用于对字符串进行转换:
1 2 3 4 5 6 7 8 9 10 11 12 |
public interface FormatProvider { /** * 把指定的值进行处理后返回 * * @param string * 要进行格式化的值 * @return 格式化好的值 * @throws FormatException */ String format(Context context, String string) throws FormatException; } |
接口方法只有一个,输入有两个参数,一个是上下文,一个是要进行格式的串,返回的值是格式化处理好的串。
当然,我也担心,一些串可能会与我们的点位符有冲突,因此期望能由用户自行指定点位符,因此设定了下面的接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
/** * 模式匹配处理接口 * * @author luoguo * */ public interface PatternDefine { /** * 返回正则匹配 * * @return */ Pattern getPattern(); /** /** /** /** /** /** /** |
当然上面的接口如果是固定一个的话,框架内部已经提供,不必另行进行扩展。
格式化接口如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/** * 格式化的接口 * * @author luoguo * */ public interface Formater extends FormatProvider { /** /** /** |
三个方法, setPatternHandle用于设定格式话模式,setFormatProviders用于设定格式化提供者,由于是一个map,key值是前缀,value是对应的格式化处理器。当然也可以通过addFormatProvider一个一个的增加出来。
好的,接口的事情就搞定了,我们来看看具体的实现类:
默认的格式化实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
public class DefaultPatternDefine implements PatternDefine {
private static final String DEFAULT_PATTERN_STRING = "([$]+[{]+[a-zA-Z0-9[.[_[:[/[#]]]]]]+[}])"; public Pattern getPattern() { public void setPrefixPatternString(String prefixPatternString) { public void setPostfixPatternString(String postfixPatternString) { public void setPatternString(String patternString) { public String getPureMatchText(String string) { public String getFullMatchText(String string) { public void setSplitChar(char splitChar) { public char getSplitChar() { } |
下面是一个针对Context的格式串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class ContextFormater implements FormatProvider {
public String format(Context context, String string) throws FormatException { |
下面是核心的格式化算法了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
public class FormaterImpl implements Formater {
private Map<String, FormatProvider> formatProviders; /** /** /** public void setFormatProviders(Map<String, FormatProvider> formatProviders) { public void setPatternHandle(PatternDefine patternHandle) { } public void addFormatProvider(String prefix, FormatProvider formatProvider) { } |
好吧,还有一些配置相关的类,由于不是关键性的,就不在这里讲了,那么接下来看示例:
增加一个常量格式化提供者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class ConstFormatProvider implements FormatProvider { Map<String, String> constMap = new HashMap<String, String>(); public String format(Context context, String key) { public Map<String, String> getConstMap() { public void setConstMap(Map<String, String> constMap) { } |
再增加一个日期格式化提供者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class DateFormatProvider implements FormatProvider { Map<String, String> constMap = new HashMap<String, String>(); public String format(Context context, String key) { public Map<String, String> getConstMap() { public void setConstMap(Map<String, String> constMap) { } |
再增加一个用于测试的POJO类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public class User { String name; int age; public String getName() { public void setName(String name) { public int getAge() { public void setAge(int age) { public User() { } public User(String name, int age) { |
好吧,我承认,前面都是做铺垫,跑龙套的,真正的秀场下面开始:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/** * 测试不存在任何标记情况 * * @throws FormatException */ public void testFormatNotPlaceholder() throws FormatException { assertEquals("this is test", formater.format(context, "this is test")); } /** /** public void testFormatExistPlaceholderNoProvider() throws FormatException { /** public void testFormatBean() throws FormatException { } |
下面总结一下:
上面的格式化占位符方式是${...}方式的,中间的...可以是aa:bb的方式,或者直接是bb的方式,冒号前面实际是一个区域的概念,表示由对应的区域处理器进行处理。这样就可以由开发人员不断的扩展格式化处理器的处理能力。由于占位匹配器也是可以进行扩展的,因此,可以自行定义自己的格式化占位方式。
对于对象的属性可以无限向下“.”下去,当然也可以添加其它的处理方式,比如:数组之类的。
所以从功能及定位来说,与@Brin想写程序 是一样的。
剧透一下:当时我本来是想写模板语言的,后来直接选择复用Velocity了,所以,就只到此为止了。
虽然放弃了,但是其中在设计及基础构架方面的一些思想及模式,还是值得同学们参考与借鉴的。