本文将介绍一种典型的多态行为提供相同行为的不同实现(不同的 XML 解析算法),并展示了如何在Java代码中使用一个接口建立这一模型。
Android 新闻阅读器
应用程序将从热门 Android 开发人员站点 Androidster 获取一个 RSS 提要,并将它解析为一组简单的 Java 对象,您可以使用这些对象构建一个 Android ListView(参见下载部分获取源代码)。这是一种典型的多态行为提供相同行为的不同实现(不同的 XML 解析算法)。清单 1 展示了如何在 Java 代码中使用一个接口建立这一模型。
清单 1. XML 提要解析器接口
java代码:
package eoe.android;
import java.util.List;
public interface FeedParser {
List< Message > parse();
}
java代码:
public class Message implements Comparable< Message >{
static SimpleDateFormat FORMATTER =new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
private String title;
private URL link;
private String description;
private Date date;
// getters and setters omitted for brevity
public void setLink(String link) {
try {
this.link = new URL(link);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
public String getDate() {
return FORMATTER.format(this.date);
}
public void setDate(String date) {
// pad the date if necessary
while (!date.endsWith("00")){
date += "0";
}
try {
this.date = FORMATTER.parse(date.trim());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
// omitted for brevity
}
@Override
public int hashCode() {
// omitted for brevity
}
@Override
public boolean equals(Object obj) {
// omitted for brevity
}
// sort by date
public int compareTo(Message another) {
if (another == null) return 1;
// sort descending, most recent first
return another.date.compareTo(date);
}
}
每个解析器实现都需要提供一个 URL 给 Androidster 提要,并使用它打开一个到 Androidster 站点的 HTTP 连接。这一常见行为自然是在 Java 代码中建模,我们使用了一个抽象基类。
消息基本上是相当直观的。通过允许日期和链接作为简单的对象被访问,同时将它们表示为较强类型的对象(de >java.util.Datede > 和 de >java.net.URLde >),它隐藏了一些内部状态。它是一个典型的 Value Object,因此它基于其内部状态实现了 de >equals()de > 和 de >hashCode()de >。它还实现了 de >Comparablede > 接口,因此您可以使用它进行排序(按日期)。在实践中,提要中的数据始终是有序的,因为没有必要再进行排序。
每个解析器实现都需要提供一个 URL 给 Androidster 提要,并使用它打开一个到 Androidster 站点的 HTTP 连接。这一常见行为自然是在 Java 代码中建模,我们使用了一个抽象基类,所示。
基本提要解析器类
java代码:
public abstract class BaseFeedParser implements FeedParser {
// names of the XML tags
static final String PUB_DATE = "pubDate";
static final String DESCRIPTION = "description";
static final String LINK = "link";
static final String TITLE = "title";
static final String ITEM = "item";
final URL feedUrl;
protected BaseFeedParser(String feedUrl){
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
基类存储 de >feedUrlde > 并使用它打开了一个 de >java.io.InputStreamde >。如果出现任何差错,它会抛出一个 de >RuntimeExceptionde >,造成应用程序出现故障。基类还为标记的名称定义了一些简单的常量。显示了提要中的一些示例内容,以便于您理解这些标记的重要性。
示例 XML 提要
java代码:
< ?xml version="1.0" encoding="UTF-8"? >
< !-- generator="FeedCreator 1.7.2" -- >
< rss version="2.0" >
< channel >
< title >android_news< /title >
< description >android_news< /description >
< link >< /link >
< lastBuildDate >Sun, 19 Apr 2009 19:43:45 +0100< /lastBuildDate >
< generator >FeedCreator 1.7.2< /generator >
< item >
< title >Samsung S8000 to Run Android, Play DivX, Take Over the World< /title >
< link >< /link >
< description >More details have emerged on the first Samsung handset
to run Android. A yet-to-be announced phone called the S8000 is being
reported ...< /description >
< pubDate >Thu, 16 Apr 2009 07:18:51 +0100< /pubDate >
< /item >
< item >
< title >Android Cupcake Update on the Horizon< /title >
< link >< /link >
< description >After months of discovery and hearsay, the Android
build that we have all been waiting for is about to finally make it
out ...< /description >
< pubDate >Tue, 14 Apr 2009 04:13:21 +0100< /pubDate >
< /item >
< /channel >
< /rss >