咱們知道,要想使用單例那麼就必須定義私有構造函數來防止從類的外部來建立類的實例。在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