2011年4月24日 星期日

Simple MVC for Flex4

這是以MVC概念,寫的一個簡單範例,並沒有使用如pureMVC等框架,
單純只是把相關的各種類型的程式碼做整理而已.

以這種方式來寫mvc,不但可以降低各元件的耦合性,
同時也有容易維護的優點.
不過缺點也是有,就是這種方式如果要製作複雜或是中型以上的功能,絕對沒有用框架來的方便.

m表示model
v表示view
c表示control

model的主要功能是存取資料
view的主要功能是作視覺元件的顯示
control的主要功能是做使用者的操作

在這種分類的前提下,m-v-c三者個溝通與關聯的方式就會變成
使用者操作視覺元素->control改變了model的資料->model的資料改變了,發送通知跟view說->view知道model被改變了,所以要改變相對應的顯示->使用者看到視覺元素被改變了

換另一種說法, mvc 的互動流程為 control 改變 model , model 通知 view 去做改變.

主程式碼只用來放各物件,然後宣告mvc的變數
總共有三個物件
incButton是增加數字的按鈕
decButton減少數字的按鈕
totalsLabel是顯示目前數字的文字

FlexSimpleMVC.mxml


    
        
    
    
        
    
    
    
    
    

model是用來存放資料的,
這範例中我們只有到一個資料,就是總合,
不過為了能夠更簡化,model用來通知view的Event我並沒有另外寫在其他的class,
而是直接讓model繼承了可以廣播事件的EventDispatcher,
這樣不但model可以廣播事件,同時也不會多太多沒用的功能.

Model.as
package mvc {
    import flash.events.Event;
    import flash.events.EventDispatcher;

    public class Model extends EventDispatcher {
        public static const MODEL_CHANGE:String="modelChange";//設定一個靜態字串來表示事件名稱,到時候就用這名字直接把事件打出去!!!

        private var _totals:int;//要存的資料,數字的總和

        public function Model() {
            _totals=100;//給他一個初始值100
        }
        //寫get方法,才能夠讓view拿到這數字去顯示,不過沒用到的變數就不用寫get的,不然到時候寫程式的時候,提示多一堆沒用的東西以外,還會不小心寫錯~
        public function get totals():int {
            return _totals;
        }
        //這就是重點了,當別人改變model裡面的totals這數字的時候,就發送一個事件出去,至於這事件的名字就是剛剛在最上面宣告的靜態常數字串MODEL_CHANGE
        public function set totals(value:int):void {
            _totals=value;
            dispatchEvent(new Event(Model.MODEL_CHANGE));//直接寫成"modelChange"也可以,不過這樣比較好看也不容易弄錯
        }

    }
}
model改變的時候,會發送通知給view,
至於view要怎麼知道model被改變了呢???就是利用as3的事件嚕!!
這也是為什麼剛剛要在model寫自訂事件"modelChange"的原因.

既然model會廣播MODEL.MODEL_CHANGE的事件,
所以view在設定model的時候,同時對model作MODEL.MODEL_CHANGE事件的偵聽!!

View.as
package mvc {
    import flash.events.Event;

    public class View {
        private var _model:Model;

        public function View() {
        }

        public function get model():Model {
            return _model;
        }
       //當model的變數被設定的時候,同時對model偵聽校的事件,不然一開始沒有設定model的時候偵聽的話......是在偵聽屁嗎??保證出錯給你看!!
        public function set model(value:Model):void {
            _model=value;
            _model.addEventListener(Model.MODEL_CHANGE, onModelChangeHandler);
        }

        protected function onModelChangeHandler(e:Event):void {

        }

    }
}

因為同一個model說不定會同時讓很多view去使用,所以先寫好一個主要的view,
然後其他的view再去繼承剛剛寫好的super view!!
當然還是要把視覺元件丟進去!!
LabelView.as
package mvc {
    import spark.components.Label;
    import flash.events.Event;

    public class LabelView extends View {
        private var _label:Label;
       //把Label丟進來.
        public function LabelView(pLabel:Label) {
            //super();
            _label=pLabel;
        }

       //當model改變的時候,就...改變顯示Label
        override protected function onModelChangeHandler(e:Event):void {
            _label.text=model.totals + "";//要顯示的內容是model裡面的totals變數數值
        }
    }
}
mv都寫好了,剩下c要寫.
control的主要功能是做使用者的操作,並且去改變model裡面的數值
所以,我們把controller被實體化的同時把model丟進去,
然後再去寫各種不同改變model數值的方式
Controller.as
package mvc {
    import flash.events.MouseEvent;
    import spark.components.Button;

    public class Controller {
        public var model:Model;

        public function Controller(pModel:Model) {
            model=pModel;//把model丟進來
        }

        public function addIncButton(pButton:Button):void {
            pButton.addEventListener(MouseEvent.CLICK, onIncModelHandler);//設定增加數值的按鈕,按鈕丟進來,就偵聽"click"事件,只要按下按鈕就改變model
        }

        public function addDecButton(pButton:Button):void {
            pButton.addEventListener(MouseEvent.CLICK, onDecModelHandler);
        }

        private function onIncModelHandler(e:MouseEvent):void {
            model.totals+=1;//把model的totals總數+1
        }

        private function onDecModelHandler(e:MouseEvent):void {
            model.totals-=1;//把model的totals總數-1
        }
    }
}
最後在主程式檔裡面把mvc的東西丟進去,完成!!!

沒有留言:

張貼留言