Skip to main content

Robotlegs AS3 MVC framework in Flex project (I)

由於今天在 奶綠茶的 Robotlegs FlashAS3 MVC framework 看到他讚賞 Robotlegs AS3 MVC framework 的好用,不禁好奇的來研究一番...

其實這個 AS3 MVC framework 出現有些時日,但是一直都沒有特別的關注它。簡單看完 Robotlegs 最佳實踐,其實就可以大部分的了解 Robotlegs 運作的邏輯。不如其他的 MVC framework 有很多語言版本, Robotlegs 完全是專注在 AS3 上。也由於僅有一個版本,所以訊息傳遞是利用 AS3 Event 機制來完成,對於一些想要入門實作 MVC 的 Flash 工程師來說絕對是比 pureMVC 好入門很多...=)


Robotlegs 的重點就是搭著「 依賴注入( Dependency Injection) 」達成 MVCS 的架構,  擷取用最佳實踐的中文翻譯解釋:

Quote:
最簡單地, 依賴注入是為對象提供實例變量或屬性的行為. 當你傳遞一個變量到一個類的構造函數, 你在使用依賴注入. 當你設置一個類的屬性, 你在使用依賴注入. 如果你不是使用嚴格的過程或線性方式編寫AS3, 很可能你現在就在使用依賴注入。

呃...依賴注入? ?簡單來講一台霜淇林機,你要賣什麼口味的霜淇林就是依賴不同的原料放置到左右兩個攪拌桶內,而每一個口味可以透過介面實作來達成依賴注入。
以下是簡單的 Dependency Injection 的 Setter injection 範例:

public interface 霜淇淋介面
{
function 擠():void;
}

然後實作:

public class 巧克力 implements 霜淇淋介面{
public function 擠():void{
trace("巧克力口味的霜淇淋");
}
}
public class 草莓 implements 霜淇淋介面{
public function 擠():void{
trace("草莓口味的霜淇淋");
}
}
public class 香草 implements 霜淇淋介面{
public function 擠():void{
trace("香草口味的霜淇淋");
}
}

霜淇淋機台

public class 機台{
public var 左邊桶的霜淇淋:霜淇淋介面;
public var 右邊桶的霜淇淋:霜淇淋介面;

public function set左邊桶口味( obj:霜淇淋介面 ):void{
左邊桶的霜淇淋 = obj;
}
public function set右邊桶口味( obj:霜淇淋介面 ):void{
右邊桶的霜淇淋 = obj;
}
public function 擠綜合():void{
左邊桶的霜淇淋.擠();
右邊桶的霜淇淋.擠();
}
}

測試:

var 機台A:霜淇淋機台 = new 霜淇淋機台();
機台A.set左邊桶口味( new 巧克力 );
機台A.set右邊桶口味( new 香草 );
機台A.擠綜合(); // 香草巧克力~~

var 機台B:霜淇淋機台 = new 霜淇淋機台();
機台B.set左邊桶口味( new 草莓 );
機台B.set右邊桶口味( new 香草 );
機台B.擠綜合(); // 香草草莓


回到 Robotlegs 它用的是 轉接器 (adapter) 映射注入,就是將原料注入到一個反射庫轉接器 (SwiftSuspenders) 來用...反正就是一堆東西塞到核心反射庫轉接器內,程式用到時候自動幫你轉換取用...懶人最愛?

以下用一個很爛的範例來說明 Robotlegs 的 Injection 機制...
反正範例照貼就會出現下面的畫面~~

其實 Robotlegs 用法跟 pureMVC 很像,它也有使用 Command, Mediator, Proxy,但是又比 pureMVC 簡約很多...

先下載 最新版 Robotlegs
,解壓後 src 內的直接放到 Flex Project 的 src 下,SwiftSuspenders.swc 直接塞到 libs 下。

在 FlashBuilder 中開一個 Flex project names "RobotlegsInjectTest"

第一,做一個 MessageBox 的 mxml component 放到根目錄下:Robotlegs 的重點就是儘量不動你的 Flash/Flex class...

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:layout>
<s:VerticalLayout />
</s:layout>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var data:ArrayCollection;

private function init():void{
data = new ArrayCollection;
data.addItem("My instance name is "+ id );
}
public function update( newline:String ):void{
data.addItem( newline );
}
]]>
</fx:Script>
<s:List dataProvider="{data}" width="200" height="200" />
<s:Button label="Broadcasing" click="dispatchEvent(new Event('btnClick'))" />
</s:Group>


再來寫 MessageBox 用的 Mediator class:跟 pureMVC 一樣, viewComponent 歸 Mediator 操作

package
{
import flash.events.Event;
import org.robotlegs.mvcs.Mediator;

public class MessageBoxMediator extends Mediator
{
[Inject]
public var view:MessageBox;
//直接注入屬性,反正轉接器會自動幫你轉~~

public function MessageBoxMediator()
{
super();
}
override public function onRegister():void{
eventMap.mapListener( view , "btnClick" , onClick );
/*加入事件監聽的寫法
* 為什麼不實作 onRemove ? 機器腳體諒大家
* onPreRemove 就將一些 listener 都自動清乾淨了...懶人指數 + 1
*/這也是專攻一種語言的好處...=)
}
private function onClick(event:Event):void{
switch( event.type ){
case "btnClick":
view.update( "lalalala" );
break;
}
}
}
}


來做 Application 用的 Context...真的很類似 pureMVC 中的 Facade

package
{
import flash.display.DisplayObjectContainer;

import org.robotlegs.mvcs.Context;

public class TestRobotLegContext extends Context
{
public function TestRobotLegContext(contextView:DisplayObjectContainer, autoStartup:Boolean=true)
{
super(contextView, autoStartup);
}
override public function startup():void
{
//bootstrap here
// 預設自動化
//意思就是注入 mapping 後會自動幫你 on MessageBoxMediator...懶人指數 +1
mediatorMap.mapView( MessageBox, MessageBoxMediator );
}
}
}

最後在 RobotlegsInjectText.mxml 中寫上:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:views = "*"
minWidth="300" minHeight="300" creationComplete="new TestRobotLegContext(this)">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Label text="Robotlags framework demo 1" x="5" y="10" fontSize="16"/>
<views:MessageBox id="View1" y="40" x="10" />
</s:Application>

 

creationComplete="new TestRobotLegContext(this)"
//啟動 TestRobotLegContext


結束了~~~~~四個檔案就可以完成基本使用...也不怪乎一堆人對它的簡單入門推崇,懶人指數 X N!!!
以下有個很好的範例:
Shaun Smith 的 RobotLegs AS3: A DI Driven MVCS Framework for Flash & Flex – Inspired by PureMVC

後話:
因為目前並沒有實作過 Robotlegs 框架的中大型專案,所以沒辦法真正比較與 pureMVC 的優劣,但是看到目前為止, Robotlegs 對於想要入門實作 AS3 MVC framework 的不外乎是一個很好的選擇。尤其它與 pureMVC 有很多地方相似,對於想要學習 pureMVC 的朋友也可以是一個簡單入門的跳板。最後,想要 Flash 版的教學範例可以等奶綠茶老師的 Robotlegs 教學文章囉!

to be continue...=P

Comments

  1. 哇巫, 其實我貼就是想讓你看到, 我知道你一定會熱血, 嘿嘿, 這樣就有人可以一起討論

    ReplyDelete
  2. @milkmidi 哈哈哈哈被你陷害了,XD

    ReplyDelete
  3. 我在依賴注入的地方看很久看不太懂
    原來就是平常在用的介面==
    你解釋的真好
    謝謝你啦

    ReplyDelete
  4. RobotlegsInjectText.mxml裡的
    creationComplete="new HelloRobotLegContext(this)"
    寫錯了
    應該是
    creationComplete="new TestRobotLegContext(this)"
    才對

    ReplyDelete

Post a Comment

Popular posts from this blog

PureMVC 我也會 [6]

Mediator ViewComponents 與 pureMVC 架構的中介 監聽並反應 View Component 發出的 Event 可以發送與接收 Notification 儘量少操作 Proxy 公開方法,多用 sendNotification... Mediator design pattern 要多認識這個 Mediator 設計模式的話,請自行看連結說明啊! 簡單來講,假使有一個 View 裡面有好幾個 MovieClip 組成,而這些 MovieClip 會互相影響對方...這個情況在 Flash 中,通常都會變成下圖: MovieClip 直接控制其他 MovieClip 搞到整個關係很複雜...換一個元件簡直是災難。 加入 Mediator 後,示意圖就會變成: 這樣,所有的 MovieClip 都透過 Mediator 來跟其他 MovieClip 溝通,當某一個 MovieClip 替換成別的元件,這時候也只需要修改 Mediator 中的引用即可,是不是變得很乾淨?如果同一組 MovieClip 有另外一個操作模式,也只需要替換掉 Mediator 即可!天下太平啊~~~ 而 PureMVC 中就是利用 Mediator class 為與前端 ViewComponent 的中介,這樣可以切開 ViewComponent 與 PureMVC framework 的關係,不管你前端介面使用 Flash or Flex 製作都跟程式核心無關。 所以 ViewComponent 製作時只需要兩個原則,一把所有的請求都以 Event 送出由 Mediator 處理,二提供公開方法, Mediator 只需要監聽 View 的 Event,將收到的資訊透過公開方法喂進 ViewComponent 即可。 如在 ViewComponent 中: public function setList( result:Object ):void{ list.dataProvider = result as ArrayCollection; } //然後在按下取得資料的按鈕 Click action 寫上: dispatchEvent( new Event( "GET_LIST" )); 新建 Mediator 的時候一樣有幾個重點方...