javascript設計模式交流(一) :Singleton Pattern

來源:互聯網
上載者:User
javascript|設計  

即使是簡單的指令碼語言,應用良好的模式可以得到非常“優美”的代碼和較高的效率。
尤其是對於互動要求較高的B/S系統,非常有必要用設計模式來最佳化代碼。

單件模式(Singleton Pattern)是一種非常基本和重要的建立型模式。
“單件”的職責是保證一個類有且只有一個執行個體,並提供一個訪問它的全域訪問點。
在程式設計過程中,有很多情況下需要確保一個類只能有一個執行個體。

傳統的程式設計語言中為了使一個類只有一個執行個體,最容易的方法是在類中嵌入靜態變數,並在第一個執行個體中設定該變數,而且每次進入建構函式都要做檢查,不管類有多少個執行個體,靜態變數只能有一個執行個體。為了防止類被多次初始化,要把建構函式聲明為私人的,這樣只能在靜態方法裡建立一個執行個體。

在javascript中,雖然我們仍然可以指定靜態方法來構造對象,但由於我們不能利用建構函式的“私人”來禁止多個執行個體的產生,因此要完全實現Singleton並沒有想象中那麼簡單。

請看下面的例子:

以下內容為程式碼
<script>
function SingletonObject()
{
 SingletonObject.prototype.methodA = function()
 {
  alert('methodA');
 }
 SingletonObject.prototype.methodB = function()
 {
  alert('methodB');
 }
 SingletonObject.instance = this;
}
SingletonFactory = new Object();
SingletonFactory.getInstance = function()
{
 if(SingletonObject.instance == null)
  return new SingletonObject();
 else
  return SingletonObject.instance;
}

var instA = SingletonFactory.getInstance();
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
var instC = new SingletonObject();
instC.methodA();
alert(instA == instC); //失敗
</script>

上面的例子試圖通過傳統的方式來實現Singleton模式,而通過調用SingletonTest.getInstance()來獲得對象確實可以保證“唯一執行個體”,然而,這個例子的失敗之處在於它並沒有有效地禁止Singleton對象的構造,因此如果我們在程式碼中人工加入new SingletonObject(),仍然可以獲得到多個對象而導致模式失敗。

一個改進的替代方案如下:
以下內容為程式碼
<script>
function SingletonObject()
{
 if(SingletonObject.instance != null)
 {
  alert("不能建立多個singleton執行個體!");
  throw new Error();
 }
 SingletonObject.prototype.methodA = function()
 {
  alert('methodA');
 }
 SingletonObject.prototype.methodB = function()
 {
  alert('methodB');
 }
 SingletonObject.instance = this;
}
SingletonFactory = new Object();
SingletonFactory.getInstance = function()
{
 if(SingletonObject.instance == null)
  return new SingletonObject();
 else
  return SingletonObject.instance;
}

var instA = SingletonFactory.getInstance();
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
try
{var instC = new SingletonObject(); }//拋出異常
catch(e)
{alert('系統成功拋出了異常,阻止了instC的構造!');}
</script>

這樣當使用者試圖自己建立多個對象的時候,通過人工拋出異常來阻止。不過這麼做還是有一點點違反了"初衷",即沒有滿足“必須通過靜態方法來構造唯一執行個體”這個基本條件。因為使用者可以在最開始的時候還是可以採用new操作符來構造對象,比如在一開始寫var instA = new SingletonObject()來構造instA並不會導致拋出異常,這不能不說是這種方法的一個缺陷。

於是我們進一步思考,得到了下面第三種方法,這種方法巧妙利用了“匿名”函數的特徵來禁止對SingletonObject類建構函式的訪問,可以說比較好的類比了私人建構函式的特性,從而比較完美地解決了用javascript實現Singleton Pattern的問題。

以下內容為程式碼
<script>
(function(){
 //instance declared
 //SingletonFactory Interface
 SingletonFactory = {
  getInstance : getInstance
 }

 //private classes
 function SingletonObject()
 {
  SingletonObject.prototype.methodA = function()
  {
   alert('methodA');
  }
  SingletonObject.prototype.methodB = function()
  {
   alert('methodB');
  }
  SingletonObject.instance = this;
 }
 
 //SingletonFactory implementions
 function getInstance()
 {
  if(SingletonObject.instance == null)
   return new SingletonObject();
   
  else
   return SingletonObject.instance;
 }

})();

var instA = null;
try
{
alert("試圖通過new SingletonObject()構造執行個體!");
instA = new SingletonObject();
}
catch(e){alert("SingletonObject建構函式不能從外部存取,系統拋出了異常!");}

instA = SingletonFactory.getInstance();  //通過Factory上定義的靜態方法獲得
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();

alert(instA == instB); //成功

var instC = null;
try
{
alert("試圖通過new SingletonObject()構造執行個體!");
instC = new SingletonObject();
}
catch(e){alert("SingletonObject建構函式不能從外部存取,系統拋出了異常!");}
</script>



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。