Understanding the Framework (理解FMS框架)

FMS Framework 由 600 行没有文档的代码组成,毫无疑问很多开发者会开发自己的框架。
在本章,load几个.asc 文件,就在application中使用load()命令。比如:
main.asc:
load(”framework.asc”);
load(”components/chat.asc”);
一、Framework 的文件
让我们看看组成framework的几个文件。这里是一个简单的描述:
components.asc 加载 framework.asc 和其他的组件类。
framework.asc 组成了框架。
一个 gFrameworkFC 的单例就是在这里定义的。
gFrameworkFC 存储了对每一个组件实例的引用。
这个文件自动的加载 application.asc和 facade.asc
application.asc 是Framework所必需的。它对application 对象有了一些框架要的功能上的增强。
facade.asc 负责服务器端组件的(路由方法)method routing 和(静态实例) lazy instantiation 。是框架的第2个支柱。
component.asc 所有服务器组件类的基类。它定义了几个常用变量 (比如 prefix and callPrefix),处理事件转发和组件间的通信。
二、Framework数据结构
Framework的3个基本观点:
1 所有的东西都基于一个命名机制。
2 gFrameworkFC.components 存储了对 component classes的引用。
按照组件类型索引。
3 所有的 客户端-服务器端 的调用是通过 服务器端的Client对象。
因此被附属在Client.prototype或者它的一个子属性。
1) 所有的东西都基于一个命名机制。
ComponentClassTypeName.ComponentInstanceName.ComponentMethodName
比如    CChat.chat1_mc.sendMessage()
2) gFrameworkFC.components 数据结构
gFrameworkFC:The global framework singleton.
gFrameworkFC.components:An array indexed by component type.
gFrameworkFC.components.FCChat:A reference to the FCChat class (extended from FCComponent).
gFrameworkFC.components.FCChat.instances:An array of references to instances of the FCChat class.
gFrameworkFC.components.FCChat.instances.chat1_mc:A single instance of the FCChat class named chat1_mc. This is what you can invoke methods on.
As you can see, gFrameworkFC stores the class type name first, then the instance name, and then the method name.
如果你想调用 chat1_mc实例的clearHistory( )在 main.asc中, 你使用:
gFrameworkFC.components.FCChat.instances.chat1_mc.clearHistory( )
3) Client.prototype 数据结构
由于flashCom server的内部设计,所有的 client-to-server 调用都需要通过服务器端的 Client 对象。
因此,需要定义一种从Client到适当的组件实例的路由方法。 这种路由方法在facade.asc中定义的。
最终结果是 一堆对象 被 附着 在Client上,描述如下:
Client.prototype
The Client object’s prototype,所有的client-to-server调用自动通过。
通过 “_ _resolve” 机制,下面的数据结构就会 附着(attached to)在它上面。
Client.prototype.FCChat
FCFactory的一个实例。 FCFactory生成类的对象并且存储到gFrameworkFC.components.FCChat.instances.
Client.prototype.FCChat.chat1_mc
FCFacade的一个实例, FCFacade类将Client对象作为第一个参数传给 方法调用,然后把这个方法 送给合适的对象。
在这种情况下,Client上面附上的变量很有迷惑性。比如,Client.prototype.FCChat 是FCFactory 的实例 (not FCChat类).同样 Client.prototype.FCChat.chat1_mc是FCFacade的实例.
我们会在讨论facade.asc分析代码生成这种数据结构
三、Framework 内存管理
在一个组件实例的生命周期中,它往往要访问5种数据。
Globals。 能够被所有的用户和组件访问。 常常是 gFrameworksFC 下的一个成员。
Client globals. 用户间不同。组件间相同。 组件从 FCComponent类 继承了 getClientGlobalStorage( ) 这样在一个用户所有的地方都可以访问。比如 一个 client global 是userColor。 对于用户来说不同。但是对于一个用户所有的组件来说相同。
Component globals.对于某一种给定类型的组件来说是相同的。它常常是组件类的静态变量(static)。比如currentSpeaker。对于很多组件实例来说是相同的。
Client locals。 对于每一个用户的每个组件来说都是不同的。组件从 FCComponent类 继承了getClientLocalStorage()方法。
Component locals.对于某个给定的组件来说,它的成员变量就是的。
四、组件的注册和实例化
五、Framework 方法路由
六、Framework 的代码祥解
   framework.asc 解析。
首先。它创建了一个gFrameworkFC的对象。
这是一个单例,代表framework。
__toarray__ 用于将 obj转化为对象。
其次。它load了.application.asc和facade.asc
然后,它操作gFrameworkFC对象,定义了 nextClientID=0,然后每来一个客户端+1。
定义了gFrameworkFC的 2个number:
clientGlobals    这个Object实际上是通过client.__ID__来做index的一个array,可以通过 getClientGlobals获得每个client的全局变量。
components,在registerComponent时传入 name和class
gFrameworkFC.components[name] = componentClass;
然后,application.addListener( componentClass ), 定义了 class的 onAppStop和onDisconnect事件
注: Function的apply,call方法。
都是的第一个参数都是传入一个obj。表示在 function内部 this。 后面的就是方法本身需要传入的参数。apply后面的参数是array.call是obj。
public apply(thisObject:Object, [argArray:Array]) : Void
application.asc解析。
首先,将 flash com的事件 处理
通过,gFrameworkFC.application,分发到各个 component。
这个,每个component就可以 了。
然后 ,定义FCApplication,并且初始化 FCApplicaton的一个对象,application。
实现 gFrameworkFC.application 到 FCApplication。
桥梁是FCApplication中的一句话:
gFrameworkFC.application.addListener(this);
       facade.asc解析。
__resolve( )是server-side提供的一个方法。当一个obj的method找不到的时候就执行此方法。
这个用来将
The facade.asc file’s job is to set up client-to-server objects that route methods from the
client-side code of a component to its server-side code.
facade的主要结构是:
定义
Client—FCFactory—–FCFacade
定义了3个的__resolve( )方法并层层调用。
这样Client最终 route成功。
        component.asc
最后的一个疑惑是component.asc。 所有的客户端组件的基类。
它的代码主要的功能是用于 事件分发和组件内通信。
首先,它 load framework.asc.
然后就是构造器。组件加载时执行。
FCComponent = function( derivedTypeName, derivedType )
每一个组件都是 FCComponent的一个子类。
FCChat.prototype = new FCComponent(”FCChat”, FCChat);
FCComponent 的构造器还创建了一个静态的obj (FCChat.instances) 和一些静态方法。
比如create( ),用于创建 组件在服务器端的一个实例。
下一段代码是允许 组件范围内的 listenter.举个例子。如果你这样写,
任何FCChat的实例 的foo属性改变的时候,listObj将会被通知:
FCChat.addListener(”foo”, listObj);
derivedType.__LISTENERS__ [一个array实现的table]和addListener( )和 removeListener( ) 实现了这个机制。
FCChat.__LISTENERS__ 是一个用属性名[property names]做index的array.
它的每一项都是 一个 组件实例的引用 的 array,此array用组件的prefix来做index
举个例子,如果你想通知chat1_mc,foo 在FooComponent中 改变了,
你首先查找 FooComponent.__LISTENERS__["foo"]["FCChat.chat1_mc"]
获得一个chat1_mc 的引用,然后你再调用它的 onPropertyChanged( )
如果你知道数据结构,sendUserEvent( ) 就很容易理解了。
最后FCComponent class调用gFrameworkFC.registerComponent( ).
注意,组件类的构造器不会执行。只有当 facade.asc创建了它的一个实例,
因为facade需要将一个client-to-server的方法调用传给它。
然后,component.asc 定义了FCComponent.prototype的一些方法。
代码定义了FCComponent.prototype.init( )。这个方法在组件的构造器中调用。
它初始化了很多变量,比如name, prefix, callPrefix,这些用于 命名空间,以及server-to-client调用
然后,component.asc 定义了4个有用的方法:
getClientID( )
返回 client.__ID__
getClientGlobalStorage( )
返回每个用户的全局变量。
对于每个用户不同。但是对于每一种组件来说相同的。比如(username 或者userColor).
getClientLocalStorage( )
返回每个用户的局部变量。
它相当于每一个组件实例的局部变量,但是它附着在client对象上。
releaseLocalStorage( )
释放 客户的局部变量。内存回收。
剩下的就是事件的通知了.静态的
onWatch( ) ,addListener( ), removeListener( ), and sendUserEvent( ) 方法.
他们都是使用前面描述的__LISTENER__
唯一需要注意的是: this.watch(prop, FCComponent.onWatch);
这就是服务器端的ActionScript 如何 观察一个 特定的变量[watch,
一种当 变量值改变时通知的方法]。
注意这里对每一个变量都只有一个watcher
总结:
为什么要组件。实际上就是将服务器端的application的事件相应,变成 每一个组件的事件相应。
每一个组件都可以单独而不影响的存在。
原文地址:http://xinsync.xju.edu.cn/index.php/archives/1839

posted @ 2009-05-17 12:27  Andy  阅读(481)  评论(0编辑  收藏  举报