框架包结构的设计

这里的框架拿Flex或者FlexLite以及Egret做例子。框架的包结构划分应该是以调用关系为依据划分的,尽量把需要相互调用的类放在一个包下面。这样最终得到的结果就是各个包之间相互独立,理想情况下即使你删除一个包,其他的也不受影响。但是现实肯定不是理想的,包之间总是还有依赖。这些有依赖的东西,大部分就是框架里面核心的东西了。这时候就把这些公共依赖的部分抽出来,放到一个核心包下,比如叫core。 从另一种角度上来讲,所谓的框架”核心类”,实际上就是一些公共耦合的类。这样其他的包都和这个核心包有依赖关系,但是他们彼此之间没有依赖关系。

举一个例子:上面说到的三种框架都有一些枚举类,提供一下静态字符串,通常为其他类的某些属性提供值。再具体一点可以在Flex的spark.components包下面可以看到有一个PopUpPosition的一个枚举类,这里可能会奇怪,这个叫做components的包下面不应该都是放一些UI组件么,怎么多出了这么一个东西。别急,我们来看一下官方API描述:

PopUpAnchor.popUpPosition 属性的枚举类型。该类型描述了 PopUpAnchor 锚定的 popUp 控件的位置。该位置与 PopUpAnchor 位置相关。

这里明确指出了这个枚举类是和这个PopUpAnchor组件配套使用的,也不会作为其他类的某些属性的枚举类型。那么这个枚举类和组件放在一起也就无可厚非了。 我们再来看一下FlexLite里面的PopUpPosition这个类,同样的这也是一个枚举类,甚至全部的代码都和Flex里面的这个一样,但是这个类却不是在components包下面,而是在core包下面。同样的看一下API描述:

定义弹出位置的常量值。 该常量决定目标对象相对于父级组件的弹出位置。

看到这里结合上面所说的,那么这个类一定是和其他的某些类产生了依赖关系。在打开调用结构层次关系的时候会发现,不光是PopUpAnchor这个组件使用了这个常量,还有IToolTipManagerClient这个包含提示功能的组件接口也用到了这个,甚至DropDownList的默认皮肤以及ComboBox的默认皮肤也用到了这个弹出位置的常量,而这些在Flex里面是没有的。所有这两个类的包位置是不一致的。

通常,还有一些公共的依赖包比如managers以及layouts这些全局的管理类。还有一个utils的工具包,这些公共的类都有一个特点,就是除了依赖core包以外不会再依赖于其他的包了。再比如skins这个包,这个包提供组件的默认皮肤,我们完全可以直接删除这个包,整个框架也不会报错,但是他还是存在于框架中,因为他提供了一个默认的实现方式,方便了开发者以及调试。所有最后的结论就是,框架中包的划分是根据类的依赖关系来放,而不是类的特征。