|
Java 库的建立方法及其实例(7) 从这里可以看出,定义一个MatchResult interface然后再用Matcher来实现这个interface是一种比较好 的方法。因为,这样定义了比较好的层次结构,对于后面的扩展,程序的更新发展都有比较大的好 处。在这里也可以看出,MatchIterator的方法返回的也是MatchResult interface, 而不是Matcher类。 同时可以看到MatchIterator本身也是一个interface。这就体现了另外一个我们需要明白的重要问题: 对interface编程,而不是对类编程。具体说来,如果在以后重新写了一个新的类,叫做 AnotherMatcher, 同样也是实现MatchResult interface, 在AnotherMatcher中同样可以使用方法来返回一 个MatchIterator的实例,它也许是Matcher类的实例,也可以是AnotherMatcher类的实例。但是,虽 然我们作了很多改动,但是没有影响到以前的程序,不需要对以前的程序作任何的改动。从使用者 的角度来看,如果他只是使用了MatchResult和MatchIterator这两个interfaces中定义的方法,那么, 不论是用Matcher还是AnotherMatcher,他都不需要修改他的代码。
下一个需要看的函数是findAll().
//调用了带参数的重载函数findAll(int)
public MatchIterator findAll(){
return findAll(0);
}
/**
* Returns an iterator over the matches found by subsequently calling find(options), the search starts from t
he zero position.
*/
public MatchIterator findAll(final int options){
//setPosition(0);
//不用关心具体的实现方法,但是我们可以看到,在这里它定义了一个anonymous inner class, 这 个inner class实现了MatchIterator,用于把Matcher中匹配到的结果一个个的返回。这个inner class的 对象实例的reference被findAll()方法返回。能够用于外部的一个reference,并能读出这些结果。这也 是一种需要注意的方法。
return new MatchIterator(){
private boolean checked=false;
private boolean hasMore=false;
public boolean hasMore(){
if(!checked) check();
return hasMore;
}
public MatchResult nextMatch(){
if(!checked) check();
if(!hasMore) throw new NoSuchElementException();
checked=false;
return Matcher.this;
}
private final void check(){
hasMore=find(options);
checked=true;
}
public int count(){
if(!checked) check();
if(!hasMore) return 0;
int c=1;
while(find(options))C++;
checked=false;
return c;
}
};
}
在上面这段代码中,我们明白了如下3点:
1、对interface编程,而不是对类编程。
2、如何编写一个iterator(迭代器)。需要有起码的两个函数:hasMore(), NextElement()。这样,使用 者可以用如下循环读取迭代器中的内容:
for(;iterator.hasMore();)
iterator.NextElement();
3、把处理方法和处理结果分开。用Matcher来表示匹配的方法的具体实现,而把结果放在另外一个 类中。这样做的好处是处理方法和结果分开,更加的灵活可以任意的更改处理的方法,而结果类不 受到影响。也可以更改结果类的读取方式,但是不影响处理方法类的实现。这种方法已经被J2SE SDK中的很多集合类所使用。也可以参考它们的实现方法。
当然,还有一点需要注意的就是使用了匿名的inner class方法。
jregex中可以讨论的问题还有很多,比如它所采用的Not Finite Automata方法,它所采用的正则表达 式规范等等。但是,作为本文所讨论的范围,即如何设计和实现一个库,已经可以展示它的设计方 法了。有兴趣的读者可以到jregex.sourceforge.net下载它的源代码包,二进制文件包,使用范例和文 档说明做进一步的研究。
小结:
在本文中,我们讨论了设计和实现一个Java库的若干原则,并用一个简单的例子来说明了这些原 则。随后,我们用一个实际应用范围很广的库来讨论了其他的一些需要注意的问题。
设计原则一:封装
一个好的库必须是一个紧凑的关系紧密的整体,而不是一个分散的关系松散的对象的集合。
设计原则二:继承
采用abstract函数,interface, 和"钩子"函数。
设计原则三:调试
在库代码中加入打印调试信息的语句。
以及一些设计方法:
1、如何编写重载构造函数。
2、在一个类的实例中返回另外一个类的实例
3、对interface编程,而不是对类编程。
4、如何编写一个iterator(迭代器)。
5、把处理方法和处理结果分开。
6、如何使用inner class.
同时,我们也讨论了阅读一个Java库源代码的方法:
1、阅读API文档说明,库的树形结构,明白类,interface的关系。
2、用javap来列出类的函数说明,变量,interface中定义的函数,常量等等。
3、注意private, protected函数。 (全文完)
|