咱们知道,要想使用单例那么就必须定义私有构造函数来防止从类的外部来建立类的实例。在Scala中你也能够经过private关键字定义类的私有主构造函数来防止从类的外部建立类的实例。函数
scala> class Person private(name: String) defined class Person warning: previously defined object Person is not a companion to class Person. Companions must be defined together; you may wish to use :paste mode for this. scala> val p = new Person("Ming") <console>:12: error: constructor Person in class Person cannot be accessed in object $iw val p = new Person("Ming") ^
咱们看到在类的外部已经没法使用new关键字来实例化这个类了。那么在Scala中如何实现getInstance方法来获取这个对象的实例呢,就是在类的伴生对象中实现这个方法。this
scala> :paste // Entering paste mode (ctrl-D to finish) class Person private(name: String) object Person { def getInstance(name: String) = new Person(name) } // Exiting paste mode, now interpreting. defined class Person defined object Person scala> val p = Person.getInstance("Ming") p: Person = Person@7859bd9a
你可能发现了,这个时候Person并非一个单例对象,而只是限制了主构造函数的访问权限。其实在Scala中实现一个单例对象最简单的方式就是直接使用类的伴生对象,而不须要定义类。固然你也能够像Java中那样去实现一个单例对象。你会看到无论你调用多少次getInstance方法,获得的都是同一个对象。scala
scala> :paste // Entering paste mode (ctrl-D to finish) class Person private(name: String) object Person { private var p:Option[Person] = None def getInstance(name: String): Person = { if (!p.isDefined) { p = Some(new Person(name)) } p.get } } // Exiting paste mode, now interpreting. defined class Person defined object Person scala> val p = Person.getInstance("Ming") p: Person = Person@47d32e33 scala> val p = Person.getInstance("Li") p: Person = Person@47d32e33