1

我正在尝试使用 Scala解析来自last.fm的artist.getInfo调用。scala 的 Xml API 真的很棒,但是我有一个设计问题(也许是个人风格)。

目前,我正在从伴随对象中的 XML 中解析数据,并将它们交给类的构造函数,如下所示:

class ArtistProfile (
                      name: String,
                      musicBrainzId: String,
                      url: String,
                      images: List[Image],
                      streamable: Boolean,
                      listeners: Int,
                      plays: Int,
                      similarArtists:List[SimpleArtist]) 

object ArtistProfile {

def apply(xml: NodeSeq) : ArtistProfile = {
  val root = xml
  val name = SimpleArtist.extractName(root);
  val url = SimpleArtist.extractUrl(root);

  val musicBrainzId = root \ "musicBrainzId" text
  val images:List[Image] = Image.findAllIn(root)
  val streamable = (root \ "streamable" text) eq ("1")

  val listeners = (root \ "stats" \ "listeners").text.toInt
  val plays = (root \ "stats" \ "plays").text.toInt

  new ArtistProfile(
    name,
    url,
    musicBrainzId,
    images,
    streamable,
    listeners,
    plays,
    SimpleArtist.findAllIn(xml \ "similar"))
  }
}

如您所见,这些是很多参数。我的问题是将xml NodeSeq 传递给ArtistProfile 构造函数是否是一种更好的风格(就scala 的功能而言),所以类本身接管解析而不是伴随对象。

我问这个是因为我正在尝试编写自己的 last.fm scala 库(作为 scala 的介绍性项目),并且我希望所有对象的事情都是一致的。

  1. 通话中有一些数据可能不是每个人都需要的。使用第二种方法,如果对象列表变得更大,我可以将惰性 val 用于对象列表,否则使用正常的 val。对于程序员来说,这不会有什么不同。
  2. 另一方面,创建对象所需的数据解析现在与对象本身分离(如上面的示例)

哪种方法是解决问题的更好方法?

4

1 回答 1

4

我不确定这个问题是否有非黑即白的答案。您可以在类中放置辅助构造函数,这样您也可以从 xml 节点创建实例,而无需伴随对象。

但是,有充分的理由支持工厂模式。

  1. ArtistProfile 类可以在不影响用户代码的情况下更改,无论是在其字段中,还是更改为全新的子类
  2. 在构造函数中进行大量处理不是一个好主意,因为 JVM 不会对其进行优化
  3. 您可以缓存值而不是返回新实例,例如,如果同一配置文件被请求两次
  4. 从 OO 的角度来看,构造函数没有多大意义:对象如何构造自己?
  5. 它遵循 Scala 集合和案例类的约定,调用更简洁

正如Effective Java中提到的,工厂模式的主要缺点(假设您将主构造函数设为私有)是用户无法创建子类。

我会把它们都放在伴生对象中。

于 2012-05-23T23:49:14.187 回答