關於多型實現Singleton模式的探討 (轉)

worldblog發表於2008-01-21
關於多型實現Singleton模式的探討 (轉)[@more@]

題記:我本人也不是很喜歡這個解決辦法,但有人問起,並且資料中沒有發現其他類
似解法,所以整理成文,供大家參考討論.

關於多型實現Singleton的探討

--smilemac

 

 

Singleton模式雖然簡單,但卻是被討論最多的一個模式,為什麼呢?並不是概念問題,而是演算法問題。具體說就是singleton生命期和作用域的管理演算法問題,在不同的場景下會有不同的需要,而結構設計的意義在於將可能發生變化的部分彼此隔離開來,使他們能夠獨立的在各自的軸上發生改變,減少彼此的耦合,所以將一個可能發生爭論的演算法隔離於具體的應用環境是有意義的。:namespace prefix = o ns = "urn:schemas--com::office" />


如何實現Singleton模式的可重用性呢,即如果有若干個類都需要實現Singleton,那麼
如何才能避免每一個類都必須擁有一個獨立的Singleton演算法的複製呢?能否所有
類共用一個複製,這樣,如果需要改演算法只改一處就可以了.更進一步,能否在不同的
專案中重用這個演算法呢?

在C++中,大師Andrei Alexandrescu已給出非常好的解決辦法, 但是在一個不支援
模板的語言中,如何只使用一些基本技術,如類的封裝和執行期多型技術,來實現可
重用的Singleton模式呢? 本文試圖給出一種下面這段程式碼所示的解決辦法.

[
這段程式碼用偽寫成:],由於筆者對於java非常不熟,所以只好是偽java,請讀者
海涵. 感謝網友henry_zhou提出的問題,使我有機會思考. 這種解決辦法也可能不
對,所以請大家指出以一起探討正確的答案.如轉載討論,也請註明出處.

同時由於筆者對java的泛型支援程度不太瞭解,因此不排除java裡有更好的解決方
案.本文僅假設語言可提供的支援只是最基本的物件導向特徵.
]

//package1;
class Singleton
{
  protected Singleton _instance;
  public Singleton(Singleton _inst)
  {
  _instance = _inst;
  }
   public virtual Singleton getInstance()
  {
  if (_instance.get() == null)
  _instance.create();
  return _instance.get();
  }
  protected virtual Singleton get()
  {
  //error handler code;
  }
  protected virtual void create()
  {
  //error handler code;
  }
}

class SingletonThreadSafe : public Singleton
{
  public SingletonThreadSafe(Singleton _inst);
  public virtual synchronized Singleton getInstance()
  {
  if (_instance.get() == null)
  _instance.create();
  return _instance.get();
  }
}

//package2
class MyBaseClass : public Singleton
{
  protected MySubClassXXX();

  ......
}

class Instance_base : public Singleton
{
  private static MyBaseClass _instance;
  public Instance_base(){};
  protected virtual MyBaseClass get()
  {
   return _instance;
  }
  protected virtual void create()
  {
  if (_instance == null)
  _instance = new MyBaseClass;
  }

}

//package3;
class MySubClassXXX : public MySubClass

  protected MySubClassXXX();
  ......
}

class Instance_XXX : public Instance_base
{
  private static MySubClassXXX _instance;
  public Instance_base(){};
  protected virtual MySubClassXXX get()
  {
  return _instance;
  }
  protected virtual void create()
  {
  if (_instance == null)
  _instance = new MySubClassXXX;
  }
}

//client e.g.,;
Singleton singGen = new SingletonThreadSafe(new Instance_XXX());
MySubClassXXX myObj = down_cast(singGen.getInstance());

這段程式碼利用了所謂class-oriented語言的一個特點:同一個類的物件可以相互訪
問彼此的內部成員,即訪問控制是在類一級,而非物件一級.而在java中,訪問控制則
是放寬到同一個package.這樣,我們就可以將get和create這些可能使singleton崩
潰的設計為protected.

對於每一個子類,都需要實現它的instance類,這其實是一個instance
holder.在大多數的Singleton的實現程式碼中,instance holder是與使用者類合在一
起的.在這裡,如果使用者子類可以以低成本來建立一個的物件,所謂安全,是指創
建不會影響singleton例項物件,而所謂低成本,是指初始化的代價可以接受,如果
這些條件都滿足,那麼也可以將instance holder併入使用者類中,使用時用特定的構
造函式建立一個啞元來代替new Instance_XXX().但分開可能更具一般意義.

這樣,Singleton和SingletonThreadSafe都是可重用的,並且這棵繼承樹可以自行擴充套件. 提供不同pe下的Singleton, 如thread scope singleton(在使用多執行緒的併發中用),process scope singleton, system scope singleton, DCE scope singleton等等,或基於其他考慮的,如特定機器,等因素的singleton。

從本文中也可看到,Singleton模式的關鍵在必須有instance holder. 所以其他如
getInstance()函式是否靜態,則不是必須(這是不少網友對singleton模式的誤解
).一旦理解這一點,其實剩下的就比較容易了.但這種方法有一個不足之處,就是必
須使用難看的downcast.

最後補充說一下,不少人理解的可重用性就是copy/paste,或者需要少量
refactory的重用,而真正理想的可重用性是非侵入性的.本文試圖給出的也是這樣
一個方案.


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-997900/,如需轉載,請註明出處,否則將追究法律責任。

相關文章