Egret應用開發實踐(02) MVC 模塊化

簡介

模塊化兩個概念:git

  • 軟件設計模塊化github

  • 軟件代碼模塊化數據庫

軟件設計模塊化——分層——MVC——PureMVC設計模式

軟件代碼模塊化——JavaScript模塊化——CommonJS——WebPack服務器

軟件設計模塊化

分層是將一個複雜的程序進行層次劃分。爲每一層進行設計,每層都是內聚的並且只依賴與它的下層。採用標準的架構模式來完成與上層的鬆散關聯。將全部與領域模型相關的代碼都集中在一層,而且將它與用戶界面層、應用層和基礎結構層的代碼分離。領域對象能夠將重點放在表達領域模型上,不須要關心它們本身的顯示、存儲和管理應用任務等內容。這樣使模型發展得足夠豐富和清晰,足以抓住本質的業務知識並實現它。架構

MVC

MVC全名是Model View Controller,是模型(Model)-視圖(View)-控制器(Controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯彙集到一個部件裏面,在改進和個性化定製界面及用戶交互的同時,不須要從新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。mvc

圖片描述

MVC主要把邏輯層和表現層進行了解耦,將一個問題劃分紅了不一樣的關注點。加強了應用的穩定性,易修改性和易複用性。app

  • 視圖(View):就是用戶看到並與之交互的界面。它不作數據邏輯方面的工做,一般來講就是顯示從模型中得到的數據,或者獲取用戶的操做。當模型更新時,它須要得知模型已經更新並獲取更新後的數據以刷新界面。所以須要在模型處註冊關注該模型的視圖,以便模型通知視圖更新顯示。框架

  • 模型(Model):用於封裝與應用程序的業務邏輯相關的數據以及對數據的處理方法。「模型」有對數據直接訪問的權力,例如對數據庫的訪問。所以它經常也用來與遠程服務器做交互,做爲一個與外界訪問的代理。加載外部資源,如圖片,xml等也是在這裏操做。模型不關心本身會被如何操做或顯示,只要在數據更新時,向關注它的視圖發送通知則可。模塊化

  • 控制器(Controller):自己不做業務邏輯操做,它負責關聯視圖和模型,就像一個紐帶同樣。同時它也負責應用的流程。一般控制器會得到模型和視圖的實例,而後條用它們內部的函數。

PureMVC

PureMVC 是在基於模型、視圖和控制器 MVC 模式創建的一個輕量級的應用框架,這是一個開源框架,它最初是被用於 ActionScript 3 語言使用的 Adobe Flex、Flash 和 AIR 之上,如今已經移植到幾乎全部主要的軟件平臺之上。

圖片描述

構造PureMVC應用

在 PureMVC 實現的經典 MVC 元設計模式中,Model、View 和 Controller 分別由一個單例類來管理,合稱爲核心層或核心角色。 另外,在 PureMVC 中還提供了一個單例類 —— Façade,主要做用是做爲與核心層通訊的惟一接口,簡化開發複雜度。

除了這幾個主要對象之外,框架還有以下類 Proxy、Mediator 和 Command。

  • Proxy 對象負責操做數據模型,與遠程服務通訊存取數據,這樣能夠保證 Model 層的可移植性。一般 Proxy 對象的引用保存在 Model 中。

  • View 保存對 Mediator 對象的引用。由 Mediator 對象來操做具體的視圖組件(View Component,它的做用還包括:添加事件監聽器,發送或接收 Notification,直接改變視圖組件的狀態。經過這樣,就能夠把視圖和控制它的邏輯分離開來。

  • Command 對象是無狀態的,只在須要時才被建立。Command 能夠獲取 Proxy 對象並與之交互,發送 Notification,執行其餘的 Command。常常用於複雜的或系統範圍的操做,如應用程序的「啓動」和「關閉」。應用程序的業務邏輯應該在這裏實現。

除了基本的對象結構之外,爲了解耦合,PureMVC 框架中引入了事件機制,這是個很是簡單觀察者設計模式,全部的事件都是一個 Notification,不一樣對象之間經過 Notification 來同步操做和交換信息。例如若是想更新界面中某個 Mediator,首先咱們定義 Notification 用於此目的,而後註冊 Mediator 監聽該 Notification,而後就能夠在程序中任何地方生成一個 Notification,經過事件機制,Mediator 就會接收到 Notification,而後更新須要的部分。整個過程 Mediator 只和 Notification 有關,沒有其餘依賴,有效的下降了對象之間的依賴程度。

Facade

PureMVC中有一個單例模式類——Facade,Facade提供了與核心層通訊的惟一接口,以簡化開發複雜度。

Facade子類——AppFacade.js

///<reference path="../../../../typings/main.d.ts"/>
import {StartupCommand} from '../controller/command/startupCommand';
import {DirectorMediator} from '../view/mediator/DirectorMediator';
export class AppFacade extends puremvc.Facade implements puremvc.IFacade {
    private static STARTUP_COMMAND: string = 'STARTUP_COMMAND:';
    private static DIRECTOR_MEDIATOR: string = 'DIRECTOR_MEDIATOR';
    public constructor(key) {
        super(key);
    }
    public initializeController() {
        puremvc.Facade.prototype.initializeController.call(this);
        this.registerCommand(AppFacade.STARTUP_COMMAND, StartupCommand);
    }
    public initializeModel() {
        puremvc.Facade.prototype.initializeModel.call(this);
    }
    public initializeView() {
        puremvc.Facade.prototype.initializeView.call(this);
        this.registerMediator(new DirectorMediator());
    }
    public getDirector(): any {
        if (this.hasMediator(AppFacade.DIRECTOR_MEDIATOR)) {
            var directorMediator = this.retrieveMediator(AppFacade.DIRECTOR_MEDIATOR);
            return directorMediator.getViewComponent();
        }
    }
    public startup() {
        this.sendNotification(AppFacade.STARTUP_COMMAND);
    }
    public static getInstance(key): any {
        var instanceMap = puremvc.Facade.instanceMap;
        var instance = instanceMap[key];
        if (instance) {
            return instance;
        }
        return instanceMap[key] = new AppFacade(key);
    }
}

類方法getInstance用於返回AppFacade的單例。Facade是pureMVC的核心,標準版的Facade只會存在一個,多核版本Facade會有多個,它的實例會在instanceMap中保存。

自定義方法getDirector()返回一個Sprite實例,做爲根場景。

PureMVC已經在框架內部實現了Observer/Notification機制,只須要使用一個很是簡單的方法從Proxy, Mediator, Command和Facade發送Notification,甚至不須要建立一個Notification實例。

Facade保存了Command與Notification之間的映射。當Notification(通知)被髮出時,對應的Command(命令)就會自動地由Controller執行。

建立的Facade子類被用來簡化「啓動」的過程。應用程序調用Facade子類的startup方法,並傳遞自身的一個引用即完成啓動,使得應用程序不須要過多瞭解PureMVC。

入口類調用AppFacade

///<reference path="../../../typings/main.d.ts"/>
import {AppFacade} from './facade/appFacade';
class App extends egret.DisplayObjectContainer {
    public constructor() {
    super();
    this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);        
    }
    private onAddToStage(event: egret.Event) {
    this.createGameScene();
    }  
    private createGameScene(): void {
        var key:string = 'GY_EGRET_PATTERN';
        var stageWidth: number = this.stage.stageWidth;
        var stageHeight: number = this.stage.stageHeight;
        var appFacade =  AppFacade.getInstance(key);        
        var director = appFacade.getDirector();
        director.width = stageWidth;
        director.height = stageHeight;
        director.render();
        this.addChild(director);     
        appFacade.startup();
    }    
}
egret.registerClass(App, "App");
window["App"] = App;

其餘

參考


Guyoung Studio

相關文章
相關標籤/搜索