ActionScript 3.0的單例模式(2009-12-21 10:17:24)
轉(zhuǎn):http://www.riahome.cn/?p=154
一. Singleton的定義:確保某個class只有一個實例,而且提供一個全局的訪問點
二.Singleton類基本上有這三個特征
大概的意思就是
1 . 有一個 private static 屬性引用類的唯一的實例(Singleton Pattern中有一個 private static 實例,它引用類的唯一的實例)
2 . 有一個 public static 方法來訪問這個實例(如果實例已經(jīng)被創(chuàng)建),或創(chuàng)建實例(如果實例還沒被創(chuàng)建)(通過一個public static method 來提供該實例的全局訪問點. [如果為空則新創(chuàng)建一個])
3 . 阻止用構(gòu)造函數(shù)實例化這個類,這個一般使用私有的構(gòu)造函數(shù)來實現(xiàn),但由于AS3不支持private的構(gòu)造函數(shù),我們只能用其他的方法(構(gòu)造函數(shù)定義為Private或使用其他方法來阻止在外部使用new來創(chuàng)建實例)
三.Singleton詳解
Singleton Pattern的關(guān)鍵在于,只允許有一個對象存在.有時候我們需要有且只有一個對象存在,如播放器播放的歌曲, 購物車中的總額等.這些類對象只能有一個實例,如果制造出多個實例,就會導致很多問題.單例模式也給了我們一個全局的訪問點,相對于全局變量來說, 單例模式采用的時lazy instantiaze,即在需要這個實例時才會創(chuàng)建.如果不需要這個實例,則永遠不會產(chǎn)生.
在ActionScript 3.0里使用單例模式(Singleton Pattern),原來也可以如此的多姿多彩!看了《Advanced ActionScript 3 with Design Patterns》一書后,才發(fā)覺以前我所寫的單例模式并不是真正的單例模式,或者說是不完美的單例模式(至少在ActionScript 3.0里不應(yīng)該那樣寫)。所謂單例,就是在整個應(yīng)用程序中有且只有一個類的實例,也就是說某個類只能被 new 一次。好文齊分享,我把它轉(zhuǎn)述如下,并收錄在我博客了(www.RIAHome.cn):
為了得到一個類的實例,你會使用 new 關(guān)鍵字,然后加上類名。這樣會調(diào)用類的構(gòu)造函數(shù)然后返回一個實例,就像這樣:
- var myObject:MyClass = new MyClass();
相信你已經(jīng)對這種實例化類的方式已經(jīng)非常熟悉,但這種方法無法控制類的構(gòu)造,所以我們準備使用一個靜態(tài)方法:getInstance()。因為它被聲明為靜態(tài)(static),所以它是屬于類而不是類的實例,不通過類的實例來調(diào)用它而直接使用類名來調(diào)用它。就像這樣:
- public class MyClass {
- public function MyClass() {}
- public static function getInstance():MyClass {
- return new MyClass();
- }
- }
要得到類的實例,我們就可以使用這個靜態(tài)的 getInstance() 方法:
- var myObject:MyClass = MyClass.getInstance();
防止類被實例化
只要能通過 getInstance() 方法得到實例,那所有工作都已經(jīng)是按計劃進行了。但,我們注意到,這樣始終不能防止他人通過 new 關(guān)鍵字來創(chuàng)建另一個實例。在一些語言里,可以把構(gòu)造函數(shù)聲明為私有(只能包內(nèi)構(gòu)造),這樣就可以解決這個問題(In other languages this problem would be solved by making the constructor private)。但在ActionScript 3.0里這是不被支持的。
這樣的話,我們只能放一個大大的“public”關(guān)鍵字來聲明構(gòu)造函數(shù)為公有的,然后寫上注釋告訴其他人:“這個類只能被實例化一次”。那是不是就沒有其它方法來防止一個類被實例化呢?一切皆有可能,方法當然是有的。我們可以利用面向?qū)ο蟮挠螒蛞?guī)則來達到目的,不正當?shù)恼Z法是被禁止的。
假如一個函數(shù)的參數(shù)沒有默認值,在沒有傳遞參數(shù)的情況下去調(diào)用這個函數(shù),編譯器就會報錯。這是ActionScript 3.0的一個新特性,這個特性同樣適用于構(gòu)造函數(shù)。ActionScript 3.0還有一個新特性,在一個類文件里可以不只寫一個類。也就是說在一個 .as 文件里可以寫多個類。與文件名相同的那個類叫主類,主類只能有一個,其它類可以是任意多個,而且其它類只對包內(nèi)可見,不能被外部引用。就像這樣:
- package {
-
- public class MyClass {
-
- public function MyClass(enforcer:SingletonEnforcer) {}
-
- public static function getInstance():MyClass {
- return new MyClass(new SingletonEnforcer());
- }
-
- }
-
- }
-
- class SingletonEnforcer {}
現(xiàn)在你只能通過以下語句來創(chuàng)建類的實例,因為你不可能在外部通過 new 關(guān)鍵字來創(chuàng)建只對包內(nèi)可見的 MyClass 類實例:
- var myInstance:MyClass = MyClass.getInstance();
注意:事實上,您還可以把 null 作為參數(shù)傳遞給構(gòu)造函數(shù)來 new 出一個 MyClass 類實例。每一種語言都不可能是完美的,但以上做法在ActionScript 3.0里已經(jīng)能基本解決問題了。
直到現(xiàn)在為止,你還不能創(chuàng)建單例,當你每次調(diào)用 getInstance() 方法時,都會創(chuàng)建一個新實例。下面我們將會了解到如何才能做到創(chuàng)建單例。
實現(xiàn)單例與全局變量
我們需要怎樣做才能保證 MyClass 類只實例化一次?現(xiàn)在,這個 getInstance() 方法可以被無限次地調(diào)用,然后無限次地 new 出很多個 MyClass 類,這無異于使用一個普通的公有構(gòu)造函數(shù)。而我們只需要一個 MyClass 類型的實例,要這樣的話,我們應(yīng)該需要一個全局變量來保存這個唯一的實例,然后每次調(diào)用 getInstance() 方法時返回這個實例而不是重新 new 一個出來。就像這樣:
- package {
-
- public class MyClass {
-
- private static var _instance:MyClass; //定義一個 Private static實例
-
- public function MyClass(enforcer:SingletonEnforcer) {}
-
- public static function getInstance():MyClass { //定一個Public static function 提供全局訪問點
- // 只有靜態(tài)的私有變量 _instance 為null時才new出一個MyClass,
- // 當?shù)诙握{(diào)用這個靜態(tài)的 getInstance() 方法時,因為 _instance 不為null,
- // 所以不再new出第二個 MyClass,而是直接返回已存在的 _instance。
- // 這樣就保證了全世界只有一個 MyClass 類型的實例
- if(MyClass._instance == null) {
- MyClass._instance = new MyClass(new SingletonEnforcer());
- }
- return MyClass._instance;
- }
-
- }
- }
-
- class SingletonEnforcer {}
至此,一個單例模式就擺在眼前了。這不是翻譯原文,跟原文已經(jīng)不同了,所以有什么說得不當請指出來,也希望通過這篇文章,您會對ActionScript 3.0里的單例模式有所認識。