Design Pattern: Registry of Singleton 模式
學習是分享和合作式的!
轉載請注明出處:https://blog.csdn.net/wdzxl198/article/details/9248821;
文章摘自: https://www.riabook.cn/doc/designpattern/;
考慮使用 Singleton 模式 時擁有子類別的問題,在Singleton模式中的getInstance()通常是一個靜態方法,不能在子類別中重新定義它,關於子類別實例的產生交由getInstance()來進行是最好的選擇,例如:
1: public class Singleton {
2: private static Singleton instance = null;
3: private Singleton()
4: {
5: // ....
6:
7: }
8: public static Singleton getInstance()
9: {
10: if (instance == null)
11: {
12: //
13: getEnv表示係統環境變數
14:
15: String style = getEnv("style");
16:
17: if (style.equals("child1"))
18: instance = new ChildSingleton1();
19: else if(style.equals("child2r"))
20: instance = new ChildSingleton2();
21: else
22: instance = new Singleton();
23: }
24: return _instance;
25: }
26: // ....
27: }
上麵這個程式片段改寫自 Gof 書中關於Singleton的例子,並用Java實現;在書中指出,這個例子的缺點是每增加一個子類別,getInstance()就必須重新修改,這個問題在Java中可以使用Reflection機製來解決:
1: public class Singleton {
2: private static Singleton instance = null;
3: private Singleton() {
4: // ....
5: }
6: public static Singleton getInstance() {
7: if (instance == null) {
8: // getEnv表示環境變數
9: String style = getEnv("style");
10: try {
11: instance = (Singleton)
12: Class.forName(style).newInstance();
13: }
14: catch(Exception e) {
15: System.out.println(
16: "Sorry! No such class defined!");
17: }
18: }
19: return instance;
20: }
21: // ....
22: }
上麵的方式使用了Java的Reflection機製,並透過環境變數設定要產生的子類Singleton,如果不使用Reflection的話,Gof 書中提出的改進方法是使用Registry of Singleton方法:
1: import java.util.*;
2: public class Singleton {
3: // 注冊表,用於注冊子類別物件
4: private static Map registry = new HashMap();
5: private static Singleton instance;
6: public static void register(
7: String name, Singleton singleton) {
8: registry.put(name, singleton);
9: }
10: public static Singleton getInstance() {
11: if (instance == null) {
12: // getEnv表示取得環境變數
13: String style = getEnv("style");
14: instance = lookup(style);
15: }
16: return instance;
17: }
18: protected static Singleton lookup(String name) {
19: return (Singleton) registry.get(name);
20: }
21: }
在Gof書中使用List來實現注冊表,而在這邊使用HasMap類別來實現,它是由Java SE所提供的;在父類別中提供一個register() 以注冊Singleton的子類別所產生之實例,而注冊的時機可以放在子類別的建構方法中加以實現,例如:
1: public class ChildSingleton1 extends Singleton {
2: public ChildSingleton1() {
3: // ....
4: // 注冊子類別物件
5: register(getClass().getName(), this);
6: }
7: }
若要利用Singleton,則先使用這個子類別產生物件,這會向父類別注冊物件,之後透過Singleton父類別來取得物件:
1: // 必須先啟始這段注冊程序
2: // 產生並注冊ChildSingleton1物件
3: new ChildSingleton1();
4: // 產生並注冊ChildSingleton2物件
5: new ChildSingleton2();
6:
7: // 注冊完成,可以使用父類別來取得子類的Singleton
8: // 至於取回何哪一個,視您的環境變數設置決定
9: Singleton childSingleton = Singleton.getInstance();
10:
事實上Registry of Singleton的真正優點正在於此,您可以使用父類別來統一管理多個繼承的子類別之Singleton實例,您可以在需要的時候再向父類別注冊子類 Singleton,必要時隨時調整傳回的子類別Singleton。
Edit by Atlas
Time 2013/7/5 09:31
最後更新:2017-04-03 16:48:30