Luar's Flash Playground:從Global Variable的創建看AS2繼承Static Class的弱點與及Singleton的濫用
從Global Variable的創建看AS2繼承Static Class的弱點與及Singleton的濫用 (23-10-2004)

在一個應用中,某Object(指Data Type)只可以有一個,即一個Global Variable給所有人共用,有以下三種可行做法:

_global

_global.luar = {age:12, gender:"M"};
這做法最簡單,在AS1經常這樣用,不過有以下缺點:
  • 不適合用於AS2,因為讀取外部東西,會破壞Object封裝性。
  • 因為數值是共用,當人人都修改過它後,要重設(Reset),怎麼辦?難道定義另一個global數值,不准別人修改?
  • 當用另一個global數值進行Reset時,例如:
    luar = luarDefault;
    這不是Object Clone,只是一個Reference指定,當別人修改luar時,等於連luarDefault都被修改了,以後永遠無法Reset。[下載範例]
  • 可以編寫一個函數,逐一屬性複製:[下載範例]
    function objReset() {
        for (var i in luar) {
            luar[i] = luarDefault[i];
        }
    }

Static Class

建立一個Class,將屬性設定為Static,並加入Reset()方法:

class SingleObject {
    private static var ageDefault:Number = 12;
    private static var genderDefault:String = "M";
    public static var age:Number = ageDefault;
    public static var gender:String = genderDefault;
    private function SingleObject() {}
    public static function reset() {
        age = ageDefault;
        gender = genderDefault;
    }
}
為了避免Class被創建多個Instance,特別將Constructor變成Private,無法使用new。[下載範例]

不過如果有另一個SingleObjectChild類繼承SingleObject類,會有一連串問題:

  • SingleObjectChild.屬性是undefined,因為Flash編譯器有Bug,如果FLA沒有引用過SingleObject類,它是不會包含在SWF裡,
  • 只有用AS1的原型鏈去實現:[下載範例]
    class SingleObjectChild extends SingleObject {
        static var __proto__ = SingleObject;
    }
    當執行範例SingleObject_4.fla,SingleObjectChild.reset()根本沒有重設SingleObjectChild屬性,換句話說,子類雖然得到了父類屬性和Method,可是Method的Scope仍然在父類裡,暈。
Singleton

Singleton(單例模式)保證Class只有一個Instance:[下載範例]

class SingletonObject {
    private static var me:SingletonObject;
    private var ageDefault:Number = 12;
    private var genderDefault:String = "M";
    public var age:Number = ageDefault;
    public var gender:String = genderDefault;
    private function SingletonObject() {
    }
    public static function getInstance():SingletonObject {
        if (me == null) {
            me = new SingletonObject();
        }
        return me;
    }
    public function reset() {
        age = ageDefault;
        gender = genderDefault;
    }
}

當執行範例SingleObject_5.fla,雖然定義2個類似Instance的Variable,但他們其實指向單一個SingletonObject Instance,所以當屬性改變時,所有人都是共用著SingletonObject Instance,因此他們裡面的數值都會改變。

如果繼承SingletonObject類:[下載範例]

class SingletonObjectChild extends SingletonObject {
    static var __proto__ = SingletonObject;
}
當執行範例SingleObject_6a和6b.fla,雖然定義2個Variables是分別向父類和子類取得Instances.但其中一個改變屬性數值,所有人都會受影響。子類reset()也能夠順利重設屬性。但是定義一個子類出來,跟父類共享屬性,實在是有點荒謬(AS2中,Private成員不是真正Private,子類可以使用父類Private成員,即等於Java中Protected成員)。Java中實現Singleton的Private Constructor,使Singleton無法繼承,AS2可惜AS2中容易墜入這種陷阱中,繼承Singleton,跟Singleton原意背道而馳,是一種濫用。

Singleton另一個陷阱,由於Singleton在Design Pattern好像比較簡單易理解,初學時就會出現什麼都用Singleton的情況,其實在這個Global Variable的探討中,利用Singleton去實現,都是一種Anti-Pattern,因為只有設計不當的應用,才需要一個Global Variable,這些Variables應該是放在他們所描述的Instances對應Classes裡,不是將他們抽出來,放在一個不相干的Singleton類裡,使這些Variables在OOD上有錯誤的依賴關係。

其他參考資料

本文章由發表。
意見
"; print "沒有意見。
 "; } ?>
  • Great!

    jackyshe於24-10-2004發表

  • luar:
    您好, 我非常想购买您的《AS2与RIA》一书..但是我身处深陆,在香港那边也没有亲戚朋友..多次与那边的电脑书店联系,他们都认为买一本书,他都难跑邮局打包裹呢..没办法之下,经过朋友介绍认识一个在香港那边的朋友,他答应我可以买到,我经过银行汇款给他后,到现在为止他没有任何音讯了,我想我是被骗了吧。。。555,对于我,一个内陆高三的学生,这是半月的伙食费啊...
    在这里我想能不能直接与您联系购买得一本.希望您能帮帮我..

    QQ:7462792
    MSN:xzskyweb@hotmail.com

    由oydj於25-10-2004發表

  • 其实anti-pattern也有很多不错的地方值得学习。可惜我算是废了,连看技术研究的书籍时间都没有了。

    7yue於26-10-2004發表

  • 其實看了您的第二本書,對於單例覺得相當好用。
    剛看了最後那幾句話我不是很清楚,(應該放在描述他們的instance裡面。)不知能否解釋清楚一點,謝謝!!

    kevin63jj於24-11-2004發表

同組文章