首页 | 源码下载 | 网站模板 | 网页特效 | 广告代码 | 网页素材 | 字体下载 | 书库 | 站长工具
会员投稿 投稿指南 RSS订阅
当前位置:主页>网络编程>java教程>资讯:面向Java开发人员的Scala指南: 增强Scitter库

面向Java开发人员的Scala指南: 增强Scitter库

www.jz123.cn  2009-09-03   来源:   IT专家网    责任编辑(袁袁)    我要投递新闻

 连接

  对于代码,第一件让我烦恼的事就是,我在 Scitter 对象和类的每个方法中都重复这样的操作序列:创建 HttpClient 实例,对它进行初始化,用必要的验证参数对它进行参数化,等等。当它们只有 3 个方法时,可以进行管理,但是显然不易于伸缩,而且以后还会增加很多方法。此外,以后重新在那些方法中引入模拟和/或本地/离线测试功能将十分困难。所以我们要解决这个问题。

  实际上,我们这里介绍的并不是 Scala 本身,而是不要重复自己(Don't-Repeat-Yourself)的思想。因此,我将从基本的面向对象方法开始:创建一个 helper 方法,用于做实际工作:

  清单 2. 对代码库执行 DRY 原则

 


 package com.tedneward.scitter
  {
  // ...
  object Scitter
  {
  // ...
  private[scitter] def exec ute(url : String) =
  {
  val client = new HttpClient()
  val method = new GetMethod(url)
  method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
  new DefaultHttpMethodRetryHandler(3, false))
  client.executeMethod(method)
  (method.getStatusLine().getStatusCode(), method.getResponseBodyAsString())
  }
  }
  }

  注意两点:首先,我从 execute() 方法返回一个元组,其中包含状态码和响应主体。这正是让元组成为语言中固有的一部分的一个强大之处,因为实际上很容易从一个方法调用返回多个返回值。当然,在 Java 代码中,也可以通过创建包含元组元素的顶级或嵌套类来实现这一点,但是这需要一整套专用于这一个方法的代码。此外,本来也可以返回一个包含 String 键和 Object 值的 Map,但是那样就在很大程度上丧失了类型安全性。元组并不是一个非常具有变革性的特性,它只不过是又一个使 Scala 成为强大语言的优秀特性。

  由于使用元组,我需要使用 Scala 的另一个特色语法将两个结果都捕捉到本地变量中,就像下面这个重写后的 Scitter.test 那样:

  清单 3. 这符合 DRY 原则吗?

 


 package com.tedneward.scitter
  {
  // ...
  object Scitter
  {
  /**
  * Ping the server to see if it's up and running.
  *
  * Twitter docs say:
  * test
  * Returns the string "ok" in the requested format with a 200 OK HTTP status code.
  * URL: http://twitter.com/help/test.format
  * Formats: xml, json
  * Method(s): GET
  */
  def test : Boolean =
  {
  val (statusCode, statusBody) =
  execute("http://twitter.com/statuses/public_timeline.xml")
  statusCode == 200
  }
  }
  }

  实际上,我可以轻松地将 statusBody 全部去掉,并用 _ 替代它,因为我没有用过第二个参数(test 没有返回 statusBody),但是对于其他调用将需要这个 statusBody,所以出于演示的目的,我保留了该参数。

  注意,execute() 没有泄露任何与实际 HTTP 通信相关的细节 — 这是 Encapsulation 101.这样便于以后用其他实现替换 execute()(以后的确要这么做),或者便于通过重用 HttpClient 对象来优化代码,而不是每次重新实例化新的对象。

  接下来,注意到 execute() 方法在 Scitter 对象上吗?这意味着我将可以从不同的 Scitter 实例中使用它(至少现在可以这样做,如果以后在 execute() 内部执行的操作不允许这样做,则另当别论)— 这就是我将 execute() 标记为 private[scitter] 的原因,这意味着 com.tedneward.scitter 包中的所有内容都可以看到它。

  (顺便说一句,如果还没有运行测试的话,那么请运行测试,确保一切运行良好。我将假设我们在讨论代码时您会运行测试,所以如果我忘了提醒您,并不意味着您也忘记这么做。)

  顺便说一句,对于经过验证的访问,为了支持 Scitter 类,需要一个用户名和密码,所以我将创建一个重载的 execute() 方法,该方法新增两个 String 参数:

  清单 4. 更加 DRY 化的版本

 


 package com.tedneward.scitter
  {
  // ...
  object Scitter
  {
  // ...
  private[scitter] def execute(url : String, username : String, password : String) =
  {
  val client = new HttpClient()
  val method = new GetMethod(url)
  method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
  new DefaultHttpMethodRetryHandler(3, false))
  client.getParams().setAuthenticationPreemptive(true)
  client.getState().setCredentials(
  new AuthScope("twitter.com", 80, AuthScope.ANY_REALM),
  new UsernamePasswordCredentials(username, password))
  client.executeMethod(method)
  (method.getStatusLine().getStatusCode(), method.getResponseBodyAsString())
  }
  }
  }

  实际上,除了验证部分,这两个 execute() 基本上是做相同的事情,我们可以按照第二个版本完全重写第一个 execute(),但是要注意,Scala 要求显式表明重载的 execute() 的返回类型:

  清单 5. 放弃 DRY

 


 package com.tedneward.scitter
  {
  // ...
  object Scitter
  {
  // ...
  private[scitter] def execute(url : String) : (Int, String) =
  execute(url, "", "")
  private[scitter] def execute(url : String, username : String, password : String) =
  {
  val client = new HttpClient()
  val method = new GetMethod(url)
  method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
  new DefaultHttpMethodRetryHandler(3, false))
  if ((username != "") && (password != ""))
  {
  client.getParams().setAuthenticationPreemptive(true)
  client.getState().setCredentials(
  new AuthScope("twitter.com", 80, AuthScope.ANY_REALM),
  new UsernamePasswordCredentials(username, password))
  }
  client.executeMethod(method)
  (method.getStatusLine().getStatusCode(), method.getResponseBodyAsString())
  }
  }
  }

  到目前为止,一切良好。我们对 Scitter 的通信部分进行了 DRY 化处理,接下来我们转移到下一件事情:获得朋友的 tweet 的列表

上一篇:Java Math 类中的新功能(一): 实数 下一篇:通过Java或Jsp向数据库存取二进制图片

评论总数:0 [ 查看全部 ] 网友评论


关于我们隐私版权广告服务友情链接联系我们网站地图