【问题标题】:Flash CS AS3 OOP Software ArchitectureFlash CS AS3 OOP 软件架构
【发布时间】:2010-02-26 21:07:51
【问题描述】:

当您使用 flash 从头开始​​构建 flash 时,它主要是 AS3,并且您使用所有外部 .as 类文件,您如何构建您的软件?你使用什么类型的全局变量结构?你的顶级课程看起来总是一样吗?您使用哪一行代码将主子显示对象附加到根 MovieClip?

【问题讨论】:

    标签: flash actionscript-3 oop architecture


    【解决方案1】:

    在 OOP Flash 中处理架构问题基本上有两种方法。任何认真的开发人员都应该熟悉的标准模型使用自定义事件。在您上面的示例中,您的 windowKnob 然后不知道该窗口 - 它只知道它是否已被按下。按下时,它会调度一个“knobPressed”事件。 Car 对象捕获该事件,然后告诉 WindowManager 打开关联的窗口。

    事件起初处理起来有点棘手,因为如何使用它们发送数据负载并不明显。也许您的旋钮可以向上或向下按下,但只发送一个事件。那么,汽车如何知道您是要打开还是关闭车窗呢?因为您将 Event 类扩展为创建的 WindowKnobEvent,并且在 WindowKnobEvent 上公开了一个名为“direction”的公共属性,该属性可以设置为向上或向下。当该事件触发并传递给您的 WindowManager 时,也许您在那里设置了一个 switch 语句以根据“direction”属性进行不同的行为 - 这有意义吗?

    因此,95% 的时间您都希望使用 Event 模型在整个应用程序中传播数据。

    但有时,使用回调可能是合适的。换句话说,您可以将 WindowKnob 对象传递给 WindowManager 中的 OpenWindow 函数的引用。由于函数都是对象,您只需说 var openWindowFunction:Function = WindowManager.openWindow,然后将 openWindowFunction 传递给您的旋钮类。

    这通常是一个坏主意:这意味着您的代码是紧密耦合的。这意味着你不能把那个旋钮放到另一辆车上——你会弄坏它,因为它不再能够保存对第一辆车的 WindowManager 的引用。但是,在某些情况下,回调可能更有效。例如,在移动设备优化中,通常最好尽量减少创建的对象数量。您调度的每个事件都使用内存。建立一次回调引用然后让它运行而不在每次有人按下旋钮时创建新的 Event 对象会更有效。

    这有帮助吗?我的意思是,AS3 OOP 架构很难在一个单一的 SO 响应中轻松总结——但我想要点是:了解事件如何工作,一切都会落实到位。除非您了解其中的含义,否则不要使用回调。

    干杯,希望对您有所帮助! 我的

    【讨论】:

    • 很好的答案。我想了解有关自定义事件结构的更多详细信息。但我有一个更普遍的问题。你如何构建你的显示对象层次结构。如果我有一辆车,而且这辆车有引擎、门和后备箱,那么我会这样做: package videogame { import flash.display.*;公共类汽车扩展电影剪辑{私有变量引擎:引擎;私人 var 门:门;私有 var trunk:Trunk;公共函数 Car() { addChild(engine = new Engine()); ... } } } 是否有必要为孩子保留实例变量?
    • 我明白你在说什么,不用担心格式。答案并不是很简单——我的意思是有一百万种方法可以做事——但一般来说,当你有一个像这样的分层对象时,实例变量是一种可靠的方法。您的汽车可以有一个成员“仪表板”,而该成员又拥有“车速表”和“无线电”等成员。还有其他方法可以解决这个问题 - 您可以有一个 ComponentManager 类,或者一个仅在需要时实例化对象的 CarPartsPool他们——但这是一个更高层次的架构讨论。
    • 根据您的能力程度和对高级编程概念的熟悉程度,您可能需要考虑使用类似 PureMVC 的 MVC 方法。 MVC 框架旨在允许您添加诸如窗口旋钮之类的东西,而无需返回并重新编程您的汽车来监听它。基本上,所有逻辑都与汽车的视觉部分分离。你的显示元素变成了位图,一个抽象的控制器监听它们的事件,然后引导它们。在此处了解更多信息:puremvc.org
    【解决方案2】:

    AS3 编程在大多数方面都应该类似于 C#、Java 或其他一些 OO 语言的编程。

    顶级课程非常相似,并以 Adob​​e 实践为蓝本。它看起来像这样:

    package 
    {
        import flash.display.Sprite;
    
        public class FirstCircle extends Sprite
        {
            public function FirstCircle( )
            {
    
            }
        }
    }
    

    将代码附加到根 MovieClip 是在 IDE 中通过在 Flash 的主要属性中输入类的名称来完成的。

    不要使用全局变量,要像在 C# 或 Java 中那样使用属性:

    private var _prop:String;
    
    public function get prop():String {
        return _prop;
    }
    

    希望这会有所帮助。

    【讨论】:

    • 我明白这一切。你用什么来进行对象到对象的通信? Main->Car->Dashbaord->Knob怎么调用Main->Car->Window->Open(),Knob显然不应该有window实例。
    • myObject.myMethod.call(myOtherObject, 1, 2, 3);
    • @Ryan 一种方法是执行以下操作:在 Knob 函数中,按下时调度自定义 Knob.Pressed 事件。 Car 对象应该监听这个。收到此事件后,汽车对象将调用 Window->Open()