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

相关文章
相关标签/搜索