4.4 单例对象

单例(参见《设计模式:可复用面向对象软件的基础》[GHJV95],Gamma等著)指的是只能有一个实例的类。单例描绘的对象扮演着中央节点的角色,它们执行诸如数据库访问、对象工厂之类的操作。在Scala里面创建单例对象非常简单。创建单例对象要用object关键字,而非class。因为单实例对象无法初始化,所以不能给它的主构造函数传递参数。

下面是单例的一个例子——MarkerFactory

ScalaForTheJavaEyes/Singleton.scala

  1. class Marker(val color: String) {
  2. println("Creating " + this)
  3. override def toString() : String = "marker color " + color
  4. }
  5. object MarkerFactory {
  6. private val markers = Map(
  7. "red" -> new Marker("red"),
  8. "blue" -> new Marker("blue"),
  9. "green" -> new Marker("green")
  10. )
  11. def getMarker(color: String) =
  12. if (markers.contains(color)) markers(color) else null
  13. }
  14. println(MarkerFactory getMarker "blue")
  15. println(MarkerFactory getMarker "blue")
  16. println(MarkerFactory getMarker "red")
  17. println(MarkerFactory getMarker "red")
  18. println(MarkerFactory getMarker "yellow")

输出如下:

  1. Creating marker color red
  2. Creating marker color blue
  3. Creating marker color green
  4. marker color blue
  5. marker color blue
  6. marker color red
  7. marker color red
  8. null

假设有个Marker类,表示对应于原色的彩笔。MarkerFactory是一个单例,它预先创建了对应三原色的Marker实例,这样就可以重用这些实例。调用getMarker()方法会根据给定的原色返回恰当的Marker实例。如果参数不是原色,则返回null。我们可以通过MarkerFactory这个名字访问它的单实例(也是它唯一的实例)。单例一旦定义完毕,它的名字就表示了这个单例对象唯一的一个实例。单例可以传给函数,就像通常传递实例一样。

不过,上面的代码有一个问题,我们可以跳过MarkerFactory直接创建Marker的实例。这个问题会在下一节得到解决。