我正在制作一个Flash AS3内置的web应用程序。
在高水平-应用程序有一个主屏幕,和几个"模态对话框"类型的屏幕,弹出管理各种用户交互。
(这是我在我开发的大多数应用程序中使用的类似模式…)
通常-当用户单击对话框屏幕上的UI控件(例如,按钮,文本框,滑动条等)-主屏幕需要做出反应,或管理结果。
似乎有两种通用的方法来处理这个问题:
- 有对话框屏幕调度事件,主屏幕监听
- 允许对话框在点击控件时调用主屏幕中的函数(这要求对话框保持对主屏幕的引用,并且主屏幕中的函数是公共的)
总的来说,我理解第一种方法的一个关键好处是对话框屏幕不是那么紧密耦合;它唯一的责任就是转播这一事件。这将允许我更容易地在其他上下文中或应用程序中使用dialog类。
但是对于我开发的许多ria—一个特定的屏幕对于应用程序来说是如此的特定,以至于我没有机会在另一个应用程序中重用它。因此,"易于重用"的好处是最小的。
那么,如果你消除了这个好处,哪种方法实际上更好?(更高的性能,更少的资源密集?)
例如,如果我使用事件,那么Flash需要管理许多可能永远不会发生的事件的侦听器。因此,如果对话框窗口可以直接调用主屏幕中的函数,而不是调度事件,那么它可能更有效。
哪种方法是更好的实践?每种方法还有什么其他好处/优点/缺点?
提前感谢。
MVC模式和许多开发人员会认为通过事件解耦逻辑是一种更好的模式。
这支持代码重用,并且在生命周期方面通常比子进程从父进程调用函数更稳定。父对象添加子对象,但是调用父对象的子对象意味着两个对象都必须感知并处理类型定义。没有办法隔离一个功能单元。
也许你的实现太具体了,抽象更多的功能会使更多的重用比你引用的更多。较大的项目可以很快达到复杂程度,使得管理纯过程模式变得困难。
程序化的实现应该向下传递,父节点保持对子节点的控制。事件向上冒泡到上升。
维护控制的子节点类似于IoC(控制反转)模式,类似于Java Spring或Swiz框架为Flash提供的。
函数将执行得更快;然而,您所说的开销是最小的,除非您说的是数千个类执行一个模式。在这种情况下,单例引擎可以帮助加速实现。
没有监听器的事件基本上没有开销。
避免让对话框知道Main screen类。紧密耦合使调试更加困难,并且不能真正代表您的意图——您的类应该只有才能访问完成任务所需的内容。任何额外的东西充其量只是额外的调试开销,最坏的情况是,会让其他必须阅读代码的人感到困惑。
如果您担心AS3事件调度系统的性能影响(您不应该担心,除非您每秒调度数百个事件),那么使用委托模式代替。因为它们使用硬引用,所以它们将非常快(很容易与直接传入Main屏幕相比),并且仍然提供松耦合的魅力。您的Dialog将不知道它正在向哪个类发送消息。与观察者/监听器模式相比,缺点是你只能得到一个"监听器"。下面是模式示例:
IDialogDelegate.as
package
{
public interface IDialogDelegate
{
function submitSelected():void;
}
}
MainScreen.as
package
{
public class MainScreen extends Sprite implements IDialogDelegate
{
private var _dialog:Dialog;
public function MainScreen()
{
super();
_dialog = new Dialog();
_dialog.delegate = this;
addChild(_dialog);
}
public function submitSelected():void
{
trace("handled!");
}
}
}
Dialog.as
package
{
public class Dialog extends Sprite
{
private var _delegate:IDialogDelegate
private var _submitButton:Button;
public function Dialog()
{
_submitButton = new Button();
_anExampleActionButton.label = "Submit";
_anExampleActionButton.addEventListener(MouseEvent.CLICK, onExampleActionSelected, false, 0, true);
addChild(_anExampleActionButton);
}
public function set delegate(value:IDialogDelegate):void
{ _delegate = value; }
private function onExampleActionSelected(event:MouseEvent):void
{
if(delegate != null)
{ delegate.submitSelected(); }
}
}
如果您喜欢冒险并喜欢运行时错误,您还可以传递用作回调的函数。您将函数从父进程传递给子进程,子进程在需要时调用该函数。