天才教育網(wǎng)合作機構 > 培訓機構 >

                                                                                        東莞設計培訓網(wǎng)

                                                                                        歡迎您!
                                                                                        朋友圈

                                                                                        全國統一學(xué)習專(zhuān)線(xiàn) 9:00-21:00

                                                                                        位置:培訓資訊 > Flash中oop的設計模式

                                                                                        Flash中oop的設計模式

                                                                                        日期:2005-12-24 00:00:00     瀏覽:280    來(lái)源:東莞設計培訓網(wǎng)
                                                                                        有人問(wèn)我flash的as應該怎么寫(xiě),我可以很負責任地告訴他,想怎么寫(xiě)就怎么寫(xiě),因為as以及flash內部的構成模式?jīng)Q定了它的高度自由化。理論上來(lái)說(shuō),用按鈕的on事件,加上stop(),play(),gotoAndStop(),gotoAndPlay(),就可以實(shí)現一個(gè)flash里大部分的邏輯關(guān)系,而且源代碼簡(jiǎn)單易懂。但是大多數人不會(huì )這么做,是因為這種方法實(shí)在太讓人敬佩。稍有常識的程序員都會(huì )知道面對對象與面對過(guò)程的區別。Flash的編程雖然只是以腳本的形式出現,并且還很不完善,比如,沒(méi)有多繼承,但已經(jīng)初步體現了oop的思想。這篇文章現在總結一下flash中面對對象的設計模式問(wèn)題,以及一些自創(chuàng )的思路。

                                                                                        設計模式是美國一位建筑大師(同時(shí)也是信息工程師,畫(huà)家,機械工程師…的)克里斯蒂安.亞歷山大首先提出來(lái)的,很快被軟件界的技術(shù)員們所接受推廣,成為軟件工程里至高無(wú)上的法則之一(有興趣的人可以找他的《建筑的永恒之道》一書(shū)看看,相信會(huì )受益非淺)。簡(jiǎn)單地說(shuō)就是在面對對象的基礎上,包括面對對象,把要設計的整體的各個(gè)部分模式化,層次化,細粒度化,高度復用化,可控化,人性化。其中至高無(wú)上的原則是建立在需求的基礎之上,也就是說(shuō),無(wú)論做什么,人的需求要放在*位考慮,從這個(gè)角度考慮整個(gè)系統是否足夠合理。這門(mén)學(xué)問(wèn)是非常有趣的,尤其在flash中,可以應用到很多很好玩的實(shí)例中去。下面我按照一些通用的設計模式,舉例說(shuō)明,有錯誤的地方,敬請高手指正:

                                                                                        1.抽象工廠(chǎng)模式(Abstract Factory)
                                                                                        食堂里吃的東西很多,而我只想吃一樣,那么食堂這個(gè)概念對我來(lái)說(shuō)就是個(gè)抽象工廠(chǎng),每個(gè)窗口可以看成它的一個(gè)具體實(shí)現,我要做的就是,去食堂,找到那個(gè)窗口,從窗口里買(mǎi)我要吃的東西。

                                                                                        舉例:flash前臺與asp后臺的交互,訪(fǎng)問(wèn)某個(gè)動(dòng)態(tài)頁(yè)面,從數據庫里取出需要的數據,通常的做法是在后臺就把數據集解析成xml字符串,再送給swf。每個(gè)業(yè)務(wù)邏輯模塊,所取出的數據結構,也就是xml的結構是不一樣的,我們要針對各個(gè)具體的業(yè)務(wù)邏輯,對相應的xml字符串解析,轉換成可供顯示的數組。也要把flash里文本輸入的內容轉換成 xml字符串,提交給后臺也面

                                                                                        AbstractFactory.as
                                                                                        //抽象工廠(chǎng)的接口
                                                                                        Interface AbstractFactory{
                                                                                        //生成xml解析工廠(chǎng)的具體實(shí)現
                                                                                        function createXmlParseFactory();
                                                                                        }

                                                                                        XMLParserGetFactory.as
                                                                                        //生成解析讀入的xml的對象的工廠(chǎng)
                                                                                        class XMLParserGetFactory implements AbstractFactory.{
                                                                                        var xmlParser;
                                                                                        function XMLParserGetFactory(){
                                                                                        //生成解析器的具體實(shí)現,在后面會(huì )提到
                                                                                        }
                                                                                        function createXmlParser(){
                                                                                        return xmlParser;
                                                                                        }
                                                                                        }
                                                                                        XMLParserPostFactory.as
                                                                                        //生成解析輸出的xml的對象的工廠(chǎng)
                                                                                        class XMLParserPostFactory implements AbstractFactory.{
                                                                                        var xmlParser;
                                                                                        function XMLParserPostFactory(){
                                                                                        //生成解析器的具體實(shí)現
                                                                                        }
                                                                                        function createXmlParser(){
                                                                                        return xmlParser;
                                                                                        }
                                                                                        }

                                                                                        這樣,我們讀入某個(gè)xml字符串時(shí),在onLoad里面加入
                                                                                        //生成對留言板的留言列表解析的工廠(chǎng)
                                                                                        var xmlParser=new XMLParserGetFactory(“xmlParseGuestbookList”)
                                                                                        xmlParser= XMLParserGetFactory. createXmlParser()
                                                                                        備注:抽象工廠(chǎng)模式是軟件工程里最常用的設計模式之一,實(shí)現過(guò)程在于,需要某個(gè)類(lèi)的實(shí)例時(shí),通過(guò)某個(gè)工廠(chǎng)創(chuàng )建,而不是直接創(chuàng )建,坦白地說(shuō),它加大了開(kāi)發(fā)工作量,但是對程序的層次性變得分明和降低耦合度有極大幫助。

                                                                                        2.生成器模式(builder)
                                                                                        還是那個(gè)說(shuō)法,我要吃東西就去相應的食堂窗口,但我不能吃食堂窗口,窗口里的東西也許不少,我要跟師傅說(shuō),要這個(gè),這個(gè),還有這個(gè)。

                                                                                        舉例:我已經(jīng)建立了 xml解析器的工廠(chǎng),現在要返回解析器本身,就讓工廠(chǎng)創(chuàng )建,返回給我。

                                                                                        XMLParserGetFactory.as
                                                                                        //生成解析讀入的xml的對象的工廠(chǎng)
                                                                                        class XMLParserGetFactory implements AbstractFactory.{
                                                                                        var xmlParser;
                                                                                        function XMLParserGetFactory(){
                                                                                        //如果要求留言板列表解析器,就生成一個(gè)
                                                                                        if(str==” xmlParseGuestbookList”){
                                                                                        xmlParser=new xmlParserGuestbookList();
                                                                                        }
                                                                                        }
                                                                                        function createXmlParser(){
                                                                                        //返回所要求的解析器
                                                                                        return xmlParser;
                                                                                        }
                                                                                        }

                                                                                        AbstractXmlParser.as
                                                                                        //抽象xml解析器
                                                                                        Interface AbstractXmlParser{
                                                                                        function ParseXml();
                                                                                        }
                                                                                        xmlParserGuestBookList.as
                                                                                        //留言板列表解析器
                                                                                        Class xmlParserGuestBookList implements AbstractXmlParser{
                                                                                        //把xml字符串里的內容解析到一堆數組里
                                                                                        function ParseXml(:Array,a){
                                                                                        //具體循環(huán)操作
                                                                                        }
                                                                                        }
                                                                                        使用的時(shí)候:
                                                                                        var xmlParser=new XMLParserGetFactory(“xmlParseGuestbookList”)
                                                                                        xmlParser= XMLParserGetFactory. createXmlParser(xml,arrayID,arrayTitle);

                                                                                        3.工廠(chǎng)方法模式(Factory Method)
                                                                                        我到了食堂窗口,如果師傅跟那兒抽煙,我還是吃不著(zhù)東西。我說(shuō):師傅,打飯!師傅才會(huì )完成打飯這一動(dòng)作。這是工廠(chǎng)方法模式,抽象工廠(chǎng)的實(shí)現通常用工廠(chǎng)方法模式來(lái)完成。

                                                                                        舉例:還是上一條,我本來(lái)想用一句話(huà)帶一個(gè)參數就實(shí)現具體xml解析器的實(shí)現,無(wú)奈構造函數沒(méi)有返回值,所以必須用
                                                                                        xmlParser= XMLParserGetFactory. createXmlParser(xml,arrayID,arrayTitle);
                                                                                        實(shí)現。

                                                                                        備注:抽象工廠(chǎng)模式,生成器模式和工廠(chǎng)方法模式需要靈活應用。


                                                                                        4.單件模式(singleton)
                                                                                        我前面一個(gè)人買(mǎi)了一條巨大的雞腿,我說(shuō)我也要一條,師傅說(shuō),就這一條

                                                                                        舉例:?jiǎn)渭J降膽檬窍喈攺V泛的,它確保每個(gè)實(shí)例在全局范圍內只被創(chuàng )建一次,我們flash里的mc大多數是單件。內核里的核心組件也只是單件,比如我的消息映射列表(見(jiàn)后)。
                                                                                        按照單件模式的嚴格定義,應該讓類(lèi)負責保存它的*實(shí)例。但是我在Flash里還想不到怎么實(shí)現這一點(diǎn),或者實(shí)現它的意義所在,但另外一點(diǎn)我們可以做到,就是在全局范圍內只提供該對象的*訪(fǎng)問(wèn)點(diǎn)。這可以由層次關(guān)系做到,把對該對象的訪(fǎng)問(wèn)具體實(shí)現全部封裝在下層,只給上層提供*的訪(fǎng)問(wèn)點(diǎn)(原因是,上層不知道這個(gè)單件的具體信息,比如路徑)。
                                                                                        看我內核文件的一部分:

                                                                                        Core.as
                                                                                        //內核
                                                                                        class Core {
                                                                                        var strucGl
                                                                                        //站點(diǎn)信息
                                                                                        var
                                                                                        //站點(diǎn)信息的xml化對象
                                                                                        var ArrayStructu
                                                                                        //用來(lái)提供給loadObject對象的數組
                                                                                        var Ar
                                                                                        //用來(lái)初始化導航條組件的數組
                                                                                        var o
                                                                                        //讀取影片的對象
                                                                                        var objM
                                                                                        //消息映射組件
                                                                                        ……
                                                                                        }
                                                                                        這是我的內核類(lèi)也就是全站最核心類(lèi)的數據結構。里面的數據只有通過(guò)下層的BasicMovie,OriginalFunctionObject等類(lèi)(見(jiàn)后)直接訪(fǎng)問(wèn)。

                                                                                        備注,核心思想是,確保只有一個(gè)。


                                                                                        5.原型模式(protoType)
                                                                                        到小炒窗口,看前面的哥們炒的青椒炒肉不錯的樣子?!皫煾?,我也要這樣的?!?BR>
                                                                                        舉例:這對flash的用戶(hù)來(lái)說(shuō)再熟悉不過(guò)了,我們經(jīng)常用duplicateMovieClip()和
                                                                                        attachMovie()這兩個(gè)函數。按照一個(gè)原型復制相應的實(shí)例,各自執行自己的動(dòng)作。在我的blog列表,導航條的生成。。幾乎用得到多項數據的地方就要用原型模式。


                                                                                        6.責任鏈模式
                                                                                        7.中介者模式
                                                                                        8.觀(guān)察者模式
                                                                                        食堂里廚房最遠的窗口沒(méi)熬白菜了,要告訴廚房,快送過(guò)來(lái)。
                                                                                        責任鏈模式:一個(gè)窗口一個(gè)窗口地傳話(huà),一直傳到食堂,食堂一看不妙,趕快做好送過(guò)去。
                                                                                        中介者模式:專(zhuān)門(mén)派一個(gè)人負責傳話(huà),任何窗口沒(méi)菜了,就要這個(gè)人趕快去廚房催。
                                                                                        觀(guān)察者模式:廚房那邊派一個(gè)盯著(zhù),看哪個(gè)窗口沒(méi)菜了就開(kāi)始大聲嚷嚷。

                                                                                        舉例:之所以要把這三個(gè)設計模式放在一塊兒,是因為我在我的站里面結合這三者建立了一個(gè)好玩的東西,可以說(shuō)是我的網(wǎng)站的核心所在。它解決了我的flash里面各個(gè)mc的通信問(wèn)題。
                                                                                        比如,影片A放完了,要通知影片B開(kāi)始播放,直接的做法是在A(yíng)的*一幀,寫(xiě)從A到B的相對路徑或B的絕對路徑,讓B play()。這樣做A和B的耦合性是相當高的,也就是說(shuō),相互依賴(lài)程度太高。運用設計模式的解決方案如下:

                                                                                        MessageMap.as
                                                                                        //消息映射類(lèi)
                                                                                        class MessageMap extends Object {
                                                                                        var
                                                                                        var Messa
                                                                                        var Target;
                                                                                        var Me
                                                                                        var Num_
                                                                                        function MessageMap() {
                                                                                        Num_Msg = 0;
                                                                                        MessageList = new Array();
                                                                                        Message = "HANG_UP";
                                                                                        MessageWatcher = function (prop, oldVar, newVar, Param) {
                                                                                        for (var i = 0; iif (newVar == MessageList[i][0]) {
                                                                                        MessageList[i][1].apply(MessageList[i][3], MessageList[i][2]);
                                                                                        if (!MessageList[i][4]) {
                                                                                        MessageList.splice(i, 1);
                                                                                        Num_Msg--;
                                                                                        i-=1;
                                                                                        }
                                                                                        }
                                                                                        }

                                                                                        };
                                                                                        this.watch("Message", MessageWatcher, "test");
                                                                                        }
                                                                                        function SendMessage( mc:MovieClip) {
                                                                                        Message = Msg;
                                                                                        }
                                                                                        function UpdateMessageMap( ob A objRefer,Is) {
                                                                                        MessageList[Num_Msg] = new Array();
                                                                                        MessageList[Num_Msg][0] = new String();
                                                                                        MessageList[Num_Msg][0] = Msg;
                                                                                        MessageList[Num_Msg][1] = new Function();
                                                                                        MessageList[Num_Msg][1] = objFunction;
                                                                                        MessageList[Num_Msg][2] = new Array();
                                                                                        MessageList[Num_Msg][2] = ArrayParam;
                                                                                        MessageList[Num_Msg][3] = objRefer;
                                                                                        MessageList[Num_Msg][4] = IsMultiUsed;
                                                                                        Num_Msg++;
                                                                                        }
                                                                                        function DeleteMessageMap(objRefer) {
                                                                                        for (var i = 0; iif (MessageList[i][2] == objRefer) {
                                                                                        MessageList.splice(i, 1);
                                                                                        Num_Msg--;
                                                                                        }
                                                                                        }
                                                                                        }
                                                                                        }

                                                                                        class SubTemplateMovie extends BaseMovie {
                                                                                        var MovieRemov
                                                                                        function SubTemplateMovie() {
                                                                                        this.stop();
                                                                                        MovieStartFunction = function () {
                                                                                        Lock();
                                                                                        this.play();
                                                                                        };
                                                                                        MovieEndFunction = function () {
                                                                                        Lock();
                                                                                        this.play();
                                                                                        };

                                                                                        MovieRemoveFunction = function () {
                                                                                        this.stop();
                                                                                        SendMsg("SUB_TEMPLATE_REMOVED", this);
                                                                                        _parent.unloadMovie();
                                                                                        };
                                                                                        MovieMainFunction = function () {
                                                                                        stop();
                                                                                        SendMsg("SUB_TEMPLATE_OPEN", this);
                                                                                        };
                                                                                        UpdateMessage("LOADING_BAR_OVER", MovieStartFunction, null, this, false);
                                                                                        UpdateMessage("BACK_TO_INDEX", MovieEndFunction, null, this, false);
                                                                                        }
                                                                                        }

                                                                                        大概機制就是,影片提前提交一個(gè)數據結構,聲明,如果有影片提交這條消息,就執行這條函數。原理在于,發(fā)送消息,實(shí)際上是把消息映射的一個(gè)變量賦值,由于消息映射繼承自object類(lèi),可以用watch方法對該變量進(jìn)行監視,一旦改變,在已經(jīng)提交上來(lái)的消息映射列表里檢查,如果有,執行對應函數。實(shí)際上這也造成了一定程度的耦合性,但是我們已經(jīng)成功地把耦合性控制在了下級類(lèi),上級子類(lèi)完全不用理會(huì )這一套消息機制的實(shí)現過(guò)程。

                                                                                        這個(gè)機制可以讓我們對oop的真正目的有更深的看法。舉例說(shuō)明,影片A播放完了,就聲明自己播放完了,至于我播完了你要干什么,不是我的事,我不控制你。所謂的降低耦合度是個(gè)相對概念,別忘了在計算機*層,耦合度還是一樣,cpu總是不斷的直接或間接尋址,但我們需要做的是,改變系統的拓撲結構,把耦合度控制在某一個(gè)范圍之內。

                                                                                        整個(gè)消息映射類(lèi)相當于一個(gè)中介者,內部生成一個(gè)觀(guān)察器,一旦觸發(fā)消息,以責任鏈的方式執行。


                                                                                        9.橋接模式(Bridge)
                                                                                        菜太淡,不合有些人的胃口,所以要求食堂的師傅,專(zhuān)門(mén)開(kāi)一個(gè)窗口,專(zhuān)門(mén)在做好的菜里多加些辣椒。

                                                                                        我在自己的站里運用了橋接模式:所有的影片都繼承自我定義的BasicMovie 類(lèi)(BasicMovie繼承自MovieClip類(lèi)),但是在四個(gè)下級欄目的影片里,需要定義相同的方法和事件來(lái)響應消息,BasicMovie沒(méi)有這些函數,不符合要求,這時(shí)候,在四個(gè)影片里都寫(xiě)一遍是愚蠢的,我又寫(xiě)了一個(gè)SubTemplateMovie類(lèi)繼承自BaseMovie,里面加進(jìn)一些通用的方法,然后四個(gè)下級模板影片都繼承它,這樣大大簡(jiǎn)化了后期開(kāi)發(fā)。

                                                                                        BasicMovie.as
                                                                                        //基類(lèi)影片
                                                                                        /所有影片的原始類(lèi),一切影片的父類(lèi)都繼承此類(lèi)而來(lái)
                                                                                        class BaseMovie extends MovieClip {
                                                                                        var
                                                                                        //初始類(lèi)開(kāi)始影片函數
                                                                                        var MovieStar
                                                                                        //初始類(lèi)影片主功能函數
                                                                                        var MovieMai
                                                                                        //初始類(lèi)結束影片函數
                                                                                        var MovieEn
                                                                                        var GlobalParam
                                                                                        //初始類(lèi)構造函數
                                                                                        function BaseMovie() {
                                                                                        }
                                                                                        //

                                                                                        //發(fā)送消息
                                                                                        function SendMsg( Mc:MovieClip) {
                                                                                        _root.objCore.objMessageMap.SendMessage(Msg, Mc);
                                                                                        }
                                                                                        //添加消息映射
                                                                                        function UpdateMessage( MsgMa ArrayParam, obj, IsMultiUsed) {
                                                                                        _root.objCore.objMessageMap.UpdateMessageMap(Msg, MsgMapFunction, ArrayParam, obj, IsMultiUsed);
                                                                                        }
                                                                                        //刪除消息映射
                                                                                        function DeleteMessage(obj) {
                                                                                        _root.objCore.objMessageMap.DeleteMessageMap(obj);
                                                                                        }
                                                                                        function GetGlobalParam() {
                                                                                        GlobalParam=_root.objCore.strucGlobalParam;
                                                                                        }
                                                                                        }

                                                                                        SubTemplateMovie.as
                                                                                        //下級模板影片類(lèi)
                                                                                        class SubTemplateMovie extends BaseMovie {
                                                                                        var MovieRemov
                                                                                        function SubTemplateMovie() {
                                                                                        this.stop();
                                                                                        MovieStartFunction = function () {
                                                                                        Lock();
                                                                                        this.play();
                                                                                        };
                                                                                        MovieEndFunction = function () {
                                                                                        Lock();
                                                                                        this.play();
                                                                                        };

                                                                                        MovieRemoveFunction = function () {
                                                                                        this.stop();
                                                                                        SendMsg("SUB_TEMPLATE_REMOVED", this);
                                                                                        _parent.unloadMovie();
                                                                                        };
                                                                                        MovieMainFunction = function () {
                                                                                        stop();
                                                                                        SendMsg("SUB_TEMPLATE_OPEN", this);
                                                                                        };
                                                                                        UpdateMessage("LOADING_BAR_OVER", MovieStartFunction, null, this, false);
                                                                                        UpdateMessage("BACK_TO_INDEX", MovieEndFunction, null, this, false);
                                                                                        }
                                                                                        }
                                                                                        注(關(guān)于消息映射機制看 責任鏈模式)


                                                                                        10.適配器模式(Adapter)
                                                                                        我要一碗湯,但是只有紙飯盒,還沒(méi)勺,所以食堂的師傅給了我一次性的湯碗和勺,這叫適配器。

                                                                                        適配器解決的是某一個(gè)類(lèi)的對外接口不合用的問(wèn)題,可能是參數或者返回值類(lèi)型不符等問(wèn)題造成的,這時(shí)候我們需要在工作對象和這個(gè)類(lèi)之間加一層間接的層次。
                                                                                        這個(gè)模式我在底層的數據交換層用過(guò)。我說(shuō)過(guò),flash和asp.net之間交換數據全以xml為載體。返回xml在底層只有三層,數據庫操作,數據操作,數據顯示,由數據操作層返回給數據顯示層一個(gè)xml字符串就可以了。然后我就遇到一個(gè)小問(wèn)題,在另一方面,我需要提交數據到數據庫,也是提交一個(gè)xml字符串,但是我需要數據庫里對應的表的數據集的xml表現形式的xsd驗證?。ㄒ豢跉庹f(shuō)完,差點(diǎn)沒(méi)憋死)。就是說(shuō)我至少需要取出這個(gè)表里的一條記錄,問(wèn)題在于,我封裝的類(lèi)從來(lái)只返回xml,沒(méi)有返回xsd的。解決辦法就是適配器,新建一個(gè)項目,加了一層專(zhuān)用于獲得xml驗證格式,這樣就完成了不同接口之間的轉換。

                                                                                        備注:適配器和橋接很象,都是在已有類(lèi)不符合要求的時(shí)候,加入一層間接的元素以達到目的。不同的是適配器是解決不兼容接口之間的轉換,橋接一般不涉及這個(gè)問(wèn)題,只是完成一個(gè)一對多的轉換。

                                                                                        11.外觀(guān)模式(Facade)
                                                                                        每天都要去食堂,每個(gè)人去不同的窗口吃不同的菜,很累,今天全寢室推舉猴子去打飯:
                                                                                        你吃這個(gè),三兩飯,我吃那個(gè),五兩飯,所有人都只跟猴子一個(gè)人交涉,食堂所有的師傅也只見(jiàn)猴子一個(gè)人。

                                                                                        舉例:這個(gè)模式在程序的上下層的通信之間可以應用得十分廣泛。Asp的每個(gè)模塊要去不同的數據,訪(fǎng)問(wèn)數據庫的不同表,就要跟不同的下層數據訪(fǎng)問(wèn)組件打交道。就是說(shuō),每個(gè)mc模塊必須知道,我要去哪個(gè)具體的數據訪(fǎng)問(wèn)組件取數據。每個(gè)模塊要維持自己的一個(gè),至少是字符串。
                                                                                        如果運用外觀(guān)模式。我們可以讓所有的需要數據交互的mc訪(fǎng)問(wèn)同一個(gè)aspx頁(yè)面,比如getStrXml.aspx。只要傳送一個(gè)標示符,就可以通知這個(gè)*的取數據的葉面,訪(fǎng)問(wèn)哪個(gè)下層組件獲取數據。下層組件不知道哪個(gè)mc要求數據,mc也不知道數據的具體來(lái)源,這樣,上下層之間互相都顯得不透明。這就降低了耦合度。


                                                                                        12.代理模式(Proxy)
                                                                                        可能我們不是每個(gè)人每天都想吃飯,所以我們要求猴子每天中午必須在寢室,如果我們要吃,他就去,如果我們都不吃,他愛(ài)干嘛干嘛。

                                                                                        舉例:這恐怕是每個(gè)人在flash里都會(huì )無(wú)意中用到的模式。比如,一個(gè)網(wǎng)站,它的下級欄目不用在整個(gè)網(wǎng)站初始化的時(shí)候一開(kāi)始就讀進(jìn)來(lái),但是我們要確保,在瀏覽者想看并且點(diǎn)擊導航條上的某個(gè)按鈕時(shí),能夠正確地讀進(jìn)相應的影片文件,前提是,我們必須在內部保留一個(gè)索引,可以稱(chēng)作代理。通常是一個(gè)空mc


                                                                                        13.策略模式(strategy)
                                                                                        我每天先在食堂找座位,再打飯,再打菜,再買(mǎi)杯酸奶。這已經(jīng)模式化。要是食堂有服務(wù)員,我也會(huì )要他這么做。

                                                                                        舉例,策略模式是把一系列的算法封裝起來(lái),形成一個(gè)類(lèi)。這個(gè)模式幾乎是隨時(shí)隨地都可以整合到別的模式里去的,我的那一堆xml解析器實(shí)際上就是策略模式的應用,這個(gè)模式還應用到我網(wǎng)站的下層,因為flash提交給aspx頁(yè)面的數據也是xml字符串,下層模塊也需要相應的解析算法。同樣的,我把對xml的解析封裝進(jìn)了一個(gè)類(lèi)。

                                                                                        //Cs文件里的解析函數

                                                                                        Class DataModel.BlogMsgs{

                                                                                        Public DataSet parseXML(string strXml){
                                                                                        DataSet ds=new DataSet();
                                                                                        //。。把xml裝載到DataSet 里
                                                                                        Return ds
                                                                                        }

                                                                                        }

                                                                                        14.享元模式(Flyweight)
                                                                                        東西不夠吃?給你擺20面鏡子~
                                                                                        師傅,東西還是只有一份。。。

                                                                                        關(guān)于這個(gè)模式十分抱歉,我暫時(shí)還沒(méi)想到在flash里面的實(shí)現。需要舉例說(shuō)明的是,瀏覽器的機制是,在有大量文字的英文文檔里,相同的字母共享一個(gè)Flyweight,在內存里其實(shí)只占一份空間,然后在文檔不同的地方顯示,這樣對于大量細粒度的效果來(lái)說(shuō),可以節省很多資源。有哪位同志想到了請一定告訴我,不勝感激。


                                                                                        15.訪(fǎng)問(wèn)者模式(Visitor)
                                                                                        只要愿意,我隨時(shí)都可以跑到哪個(gè)窗口打要吃的東西,前提是,我必須跑這一趟。

                                                                                        舉例:我說(shuō)過(guò),我的所有mc都繼承自BasicMovie這個(gè)類(lèi),但不是我的所有mc都要從后來(lái)獲取數據庫數據。獲取數據庫數據所要訪(fǎng)問(wèn)的信息,比如ip,路徑,文件保存在配置文件里,初始化的時(shí)候讀入內核,并且只有內核那里有一份。在BasicMovie里加入對這些全局變量的引用是不合適的,因為只有少數mc要用到,而且由于某些原因我無(wú)法再使用橋接模式(我已經(jīng)有了SubTemplateMovie,不能多繼承),所以我用了訪(fǎng)問(wèn)者模式。

                                                                                        BasicMovie.as

                                                                                        //獲取全局變量
                                                                                        function GetGlobalParam() {
                                                                                        GlobalParam=_root.objCore.strucGlobalParam;
                                                                                        }

                                                                                        如果上級mc不執行這個(gè)函數,是不能獲取全局變量的,如果要用,就執行。
                                                                                        也就是說(shuō),需要的時(shí)候,我去訪(fǎng)問(wèn)它。

                                                                                        備注:聲明一個(gè)visit操作,使得訪(fǎng)問(wèn)者可以正確訪(fǎng)問(wèn)需要的類(lèi)。


                                                                                        16.狀態(tài)模式(state)
                                                                                        我今天想吃面,師傅問(wèn)我:要什么料?西紅柿雞蛋,排骨還是牛肉?

                                                                                        舉例:狀態(tài)模式是指將對象當前的某些狀態(tài)局部化,當對象改變狀態(tài)時(shí),看起來(lái)好像改變了類(lèi)。例子還是我的滾動(dòng)條。如果要滾動(dòng)的是文本框,就要引用一個(gè)TextField的Scroll,maxscroll屬性,如果是mc,引用的是_y,_height屬性,我用一個(gè)參數將二者區分,由一個(gè)if語(yǔ)句控制,讓滾動(dòng)條可以自由區別狀態(tài)。
                                                                                        另外一個(gè)解決方案是定義ScrollBar的不同子類(lèi),這兩者本質(zhì)區別不大,在狀態(tài)比較多時(shí),可能要維持一個(gè)龐大的if算法,這樣就用生成子類(lèi)的方法比較好。

                                                                                        ScrollBar.as
                                                                                        //滾動(dòng)條組件
                                                                                        function BindTo(mc,:Number,){
                                                                                        ScrollType=type;
                                                                                        if(type=="TXT"){
                                                                                        scrollTxt=mc;
                                                                                        }
                                                                                        if(type=="MC"){
                                                                                        initialY=yinitial;
                                                                                        McHeight=intMcHeight;
                                                                                        scrollMc=mc;
                                                                                        }
                                                                                        }
                                                                                        function Scroll() {
                                                                                        if(ScrollType=="TXT")
                                                                                        this.onEnterFrame = function() {
                                                                                        scrollTxt.scroll = scrollTxt.maxscroll*mcBlock._y/(BgLength-BlockLength*3/2)
                                                                                        };
                                                                                        if(ScrollType=="MC"){
                                                                                        this.onEnterFrame=function(){
                                                                                        if(scrollMc._height>McHeight){
                                                                                        scrollMc._y=initialY-(scrollMc._height-McHeight)*mcBlock._y/(BgLength-BlockLength*3/2)}
                                                                                        }
                                                                                        }
                                                                                        }

                                                                                        備注:這也是常見(jiàn)模式,在flash的邏輯控制里尤其隨處可見(jiàn)


                                                                                        17.裝飾模式(Decorator)
                                                                                        在食堂吃飯,沒(méi)筷子怎么行?我是從來(lái)不帶飯盆的。師傅很人性化,每個(gè)窗口都放著(zhù)一大把筷子,隨用隨拿。

                                                                                        這個(gè)模式如果用好,有的地方可以很省力。比如,我網(wǎng)站里的滾動(dòng)條:

                                                                                        ScrollBar.as
                                                                                        //滾動(dòng)條組件
                                                                                        class ScrollBar extends BaseMovie {
                                                                                        var
                                                                                        var Bl
                                                                                        var
                                                                                        var
                                                                                        var ScrollType;
                                                                                        var
                                                                                        var
                                                                                        var
                                                                                        var
                                                                                        function ScrollBar() {
                                                                                        }
                                                                                        function InitialScrollBar(BgLength, BlockLength) {
                                                                                        this.BlockLength = BlockLength;
                                                                                        this.BgLength = BgLength;
                                                                                        }
                                                                                        function BindTo(mc,:Number,){
                                                                                        ScrollType=type;
                                                                                        if(type=="TXT"){
                                                                                        scrollTxt=mc;
                                                                                        }
                                                                                        if(type=="MC"){
                                                                                        initialY=yinitial;
                                                                                        McHeight=intMcHeight;
                                                                                        scrollMc=mc;
                                                                                        }
                                                                                        }
                                                                                        function Scroll() {
                                                                                        if(ScrollType=="TXT")
                                                                                        this.onEnterFrame = function() {
                                                                                        scrollTxt.scroll = scrollTxt.maxscroll*mcBlock._y/(BgLength-BlockLength*3/2)
                                                                                        };
                                                                                        if(ScrollType=="MC"){
                                                                                        this.onEnterFrame=function(){
                                                                                        if(scrollMc._height>McHeight){
                                                                                        scrollMc._y=initialY-(scrollMc._height-McHeight)*mcBlock._y/(BgLength-BlockLength*3/2)}
                                                                                        }
                                                                                        }
                                                                                        }
                                                                                        function ScrollMc() {

                                                                                        }
                                                                                        function StopScroll() {
                                                                                        this.onEnterFrame=null;
                                                                                        }
                                                                                        function Reset(){
                                                                                        mcBlock._y=0;
                                                                                        }
                                                                                        }

                                                                                        核心函數是BindTo(),把這個(gè)滾動(dòng)條的實(shí)例綁定到某個(gè)動(dòng)態(tài)文本框或者某個(gè)mc上,就可以實(shí)現滾動(dòng)。

                                                                                        備注:裝飾模式的思想是,在不影響其他對象的情況下,以動(dòng)態(tài),透明的方式給單個(gè)對象添加職責。


                                                                                        18.組合模式(composite)
                                                                                        我中午吃六兩飯,豬肉燉粉條,辣子雞,魚(yú)丸,咸鴨蛋,外加兩杯酸奶(豬?。?BR>這些東西都是對象,他們共同組成了我的午飯。

                                                                                        舉例:應該說(shuō)在Flash里組合模式是無(wú)處不在的,因為只要還有mc的嵌套,就有組合模式存在。幾個(gè)mc裝在一個(gè)mc里,這個(gè)裝載用的mc稱(chēng)作容器。
                                                                                        但是就這么說(shuō),恐怕沒(méi)人會(huì )重視這個(gè)模式,因為不管理不理解他我們都在用。他的確有很多種實(shí)現方式,我的方式之一是這樣的。

                                                                                        //blog.as
                                                                                        我的Blog
                                                                                        class Blog extends BaseMovie {
                                                                                        //blog*界面,包括日記列表,日歷,最近留言
                                                                                        var mcBlogList: mcBlogList;
                                                                                        //blog第二界面,包括日記全文,回復,對該日記的留言。
                                                                                        var mc
                                                                                        var cur
                                                                                        var curre
                                                                                        function blog(){
                                                                                        }
                                                                                        }

                                                                                        mcBlogList.as
                                                                                        //blog*界面
                                                                                        class mcBlogList extends BaseMovie {
                                                                                        //最近留言
                                                                                        var r
                                                                                        //日記列表
                                                                                        var
                                                                                        //日歷
                                                                                        var


                                                                                        mcblogDairy.as
                                                                                        //blog第二界面
                                                                                        class mcBlogDairy extends BaseMovie {
                                                                                        //日記全文顯示
                                                                                        var
                                                                                        //留言板
                                                                                        var
                                                                                        //留言列表顯示
                                                                                        var
                                                                                        }

                                                                                        然后里面每個(gè)組件都還包含另外的組件,比如滾動(dòng)條,動(dòng)態(tài)文本框什么的,我想說(shuō)的是,我寫(xiě)在as里的mc嵌套模式并不一定就符合fla文件里的具體物理嵌套模式,有很多裝飾性的mc不需要包含進(jìn)來(lái),也有很多具體原因,需要改寫(xiě)路徑。比如在BlogDairy下,滾動(dòng)條的實(shí)際路徑是BlogDairy.mc1.ScrollBar,不做成BlogDairy.ScrollBar可能是因為我需要mc1的動(dòng)畫(huà),也可能是別的具體原因。但是我們可以在mc1的時(shí)間軸上加一句
                                                                                        _parent. ScrollBar =This.ScrollBar
                                                                                        把路徑指向改寫(xiě),達到我們要使用的模式,ScrollBar就是BlogDairy的直接成員。另外我沒(méi)有語(yǔ)句初始化mc,我習慣在庫里設置mc的linkage。

                                                                                        備注:雖然組合模式是每個(gè)人必不可少要用的,但正因為如此,我們可以想出他更多更好更靈活的實(shí)現方式


                                                                                        19.備忘錄模式(memento)
                                                                                        ~師傅,晚上的雞腿沒(méi)中午的新鮮啊。
                                                                                        ~胡說(shuō)!這就是中午的。

                                                                                        舉例:開(kāi)個(gè)玩笑,上面兩句話(huà)不是備忘錄模式的本意,實(shí)際上我一時(shí)想不出在食堂里備忘錄是什么樣子。備忘錄的意思是,在不破壞對象封裝型的前提下,保存對象的當前狀態(tài),當需要時(shí),恢復這個(gè)狀態(tài)或提取這個(gè)狀態(tài)。

                                                                                        備忘錄被廣泛地運用到邏輯關(guān)系里,它似乎是目前我提到的*跟時(shí)間有關(guān)的模式,在控制論里可以涉及到因果系統。備忘錄的應用非常廣泛,最常見(jiàn)的是瀏覽器或網(wǎng)站的后退功能,返回到上一個(gè)界面,但是在我的站里沒(méi)有用到,因為我的站是樹(shù)狀拓撲結構,每個(gè)欄目都只能*地從主界面進(jìn)入或退回到主界面,那些網(wǎng)狀拓撲結構的站點(diǎn),每個(gè)欄目都可以通向其他的任何欄目,很可能就需要這么一個(gè)功能,其實(shí)現方法往往是維持一個(gè)堆棧型的數組。

                                                                                        另外一個(gè)我想實(shí)現的東西是網(wǎng)站內部自動(dòng)記錄,由于某些原因我暫時(shí)沒(méi)有把它加到網(wǎng)站里。很簡(jiǎn)單,就是監視瀏覽者的每一步操作,在哪個(gè)欄目,停了多久,做了些什么之類(lèi),如果離開(kāi)了,下次訪(fǎng)問(wèn)網(wǎng)站時(shí)讓他選擇是否直接進(jìn)入上次瀏覽的界面(比如他上次在看我寫(xiě)的小說(shuō)而沒(méi)看完)。這個(gè)可以通過(guò)sharedObject實(shí)現,差不多也就是flash內部的cookie。

                                                                                        備注:備忘錄的實(shí)現要求還是很高的,在提取對象狀態(tài)的時(shí)候不要破壞對象的封裝性。理想的備忘錄作為一個(gè)對象需要兩個(gè)借口,一個(gè)給管理者,它不知道備忘錄里封裝了什么狀態(tài),只負責地把狀態(tài)移交給需要的對象,一個(gè)留給原發(fā)者,原發(fā)者只能了解并操作備忘錄里封裝的狀態(tài),不能做別的操作。


                                                                                        小結:
                                                                                        我會(huì )隨時(shí)補充這篇文章。但是我要舉的一些例子暫時(shí)已經(jīng)說(shuō)完了。其實(shí)設計模式遠遠不止這幾種,經(jīng)典的有23種,我已知的有41種,而這里只有19種,還有命令模式,解釋器模式,迭代器模式,模板方法模式我沒(méi)寫(xiě)到。我的站還用了一些我沒(méi)有提到的,自己都還沒(méi)細想過(guò)的設計模式。但是一一列舉其實(shí)是意義不大的,有興趣的同志們要做的就是接觸一下這些設計模式的細節和思想,然后統統忘掉,就和張無(wú)忌學(xué)太極拳,先學(xué)后忘是一樣的。招式要看,要學(xué),但是要領(lǐng)會(huì )其中的深意,靈活地,創(chuàng )造地,相互結合,融會(huì )貫通地使用招式,不能拘泥于招式,更不能為了用招而用招。設計模式作為UML的重要組成部分,能夠極大程度地促進(jìn)我們的開(kāi)發(fā)效率,使我們養成好的書(shū)寫(xiě)習慣,做出更人性,更和諧,更清晰,復用性和可控性更高的作品。
                                                                                        不要說(shuō)你不是程序員,就可以跟著(zhù)感覺(jué)走,隨心所欲,當然我們無(wú)權干涉。我也說(shuō)了,as本來(lái)就是想怎么寫(xiě)就怎么寫(xiě),但接不接觸,學(xué)不學(xué)習先進(jìn)的思維模式,這也是你的自由。更不要說(shuō)你是搞藝術(shù)的,頭腦偏重感性,不適合接觸這些,我之所以要順帶拿食堂舉例,是想說(shuō)明,我要說(shuō)的其實(shí)是就Christian Alexander先生的,建筑的永恒之道,無(wú)論是建筑本身,還是任何軟件工程,或者Flash 的as,甚至Flash 的矢量繪圖,美工,平面設計,一直到世界這一整體,無(wú)不是遵循一個(gè)結構化的,由模式構成的永恒之道,有著(zhù)驚人的高度相通和相似性。參悟了這一點(diǎn),不僅對做Flash,對整個(gè)生活都會(huì )有新的看法。區別僅僅在于,從哪里開(kāi)始入手思考,在這里,可以從Flash開(kāi)始。

                                                                                        如果本頁(yè)不是您要找的課程,您也可以百度查找一下:

                                                                                        奇米在线7777在线精品|国产成人精品免费视|精品无码不卡一区二区三区|国内综合精品午夜久久资源|亚洲视频在线观看..