但是Singleton的想法基礎非常簡單,應用程式的執行中,就是「保證特定型的實例只能有一個存在」。
幾乎所有語言都能夠創造出無數個實例,直到J2SE 5以前,Java並沒有直接可以限制實例數的方法。J2SE 5以後的版本,
使用enum構造就可以限制特定型的物件的數量。以及也可以將已經知道的實例各自的取上名字。
C和C++等的語言,enum(列舉)是一個簡單的連串整數,每個都對應到一個Symbol。藉由使用enum,可以做出更有表現力的程式碼。
在Java裡的enum一見之下跟其他語言一樣,但是有幾個重要的不同點,enum本身可以持有建構子、方法、甚至是欄位等,但是卻沒辦法Subclass化。
以enum的定義來看,已知實例的名字已經在最初就指定好了,所以其他的實例不管用什麼方法都沒辦法作成。
單純的來想,Singleton Pattern的範例大概就會想到圖書館系統裡的目錄。無法瞭解每本書被加入到哪個目錄是我們不希望的狀況,
在下面的List1是使用了enum構造,創造出Singleton的目錄並實裝的範例。
import java.util.*; public enum Catalog { soleInstance; private Map<String,Book> books = new HashMap<String,Book>(); public void add(Book book) { books.put(book.getClassification(), book); } public Book get(String classification) { return books.get(classification); } }
並不是這麼困難的事情吧~看完上面後~Client code就知道了一定得使用已知的單一物件soleInstance了~
下面是List2(Client Code)
import static org.junit.Assert.*; import org.junit.*; public class CatalogTest { @Test public void singleBook() { Book book = new Book("QA123", "Schmidt", "Bugs", "2005"); Catalog.soleInstance.add(book); assertSame(book, Catalog.soleInstance.get("QA123")); } }
如果想要直接實例化Catalog物件的話會無法編譯
new Catalog(); // this won't compile!
大部分的開法者大概比較熟悉自己完結型的Singleton的概念吧。在Java裡是使用static方法,並將建構子設為private的意思。
下面是自我完結型的例子(List3)
import java.util.*; public class Catalog { private static final Catalog soleInstance = new Catalog(); private Map<String,Book> books = new HashMap<String,Book>(); public static Catalog soleInstance() { return soleInstance; } private Catalog() { // enforce singularity } public void add(Book book) { books.put(book.getClassification(), book); } public Book get(String classification) { return books.get(classification); } }
藉著private的建構子,就可以保證其他的client無法作成Catalog物件,從Client的觀點來看的話,並看不出什麼太大的差別。(參考List4)
import static org.junit.Assert.*; import org.junit.*; public class CatalogTest { @Test public void singleBook() { Book book = new Book("QA123", "Schmidt", "Bugs", "2005"); Catalog.soleInstance().add(book); assertSame(book, Catalog.soleInstance().get("QA123")); } }這樣看來好像是一個單純無害的Pattern,不過到底是什麼原因讓它受到如此多的批評呢?
Singleton只不過是將全域變數換成物件導向的表示法而已!在軟體開發裡,很早以前全域變數引起的問題就被發現了。
最大的問題是,全域變數是跟整個應用程式是緊密結合的。
首先要先檢討的是,全域變數跟Singleton的使用是真的必要的嘛?在現實上,主目錄只會有一個,但是設計一個Catalog類裡books的HashMap定義為static封裝是可能的。
在這種時候,Client會根據必要而複數作成Catalog實例,但是全部都指向相同的static欄位(順帶一提,這種Pattern叫做Monostate)
對於全域變數和Singleton的否定聲音非常多,但是毫無疑問這是一個正當的構造。
http://japan.internet.com/developer/20080826/26.html
No comments:
Post a Comment