AS3/Flash:子组件调用父对象的方法是不是很糟糕?

Tho*_*mas 0 oop flash actionscript-3

我有一个非常简单的场景,它有效,但我的直觉告诉我,我犯了一个错误,并想通过一些更好的头脑来运行它.

这里我有一个父类,它实例化一个MenuClass并处理页面之间的转换.

public class ParentClass extends Sprite
{
    public function ParentClass()
    {
        setupOptionMenu();
    }

    private function setupOptionMenu() : void
    {
        var myMenu:MenuClass = new MenuClass;
        myMenu.setUpButtons();
        this.addChild( myMenu );
    }

    + public function transitionForward() : void

    + public function transitionBackward() : void
}
Run Code Online (Sandbox Code Playgroud)

这里是MenuClass,它创建了前进和后退按钮.单击每个将分别告诉上面的ParentClass transitionForward()或transitionBackward().

public class MenuClass extends Sprite
{
    public function MenuClass()
    {
        setupButtons();
    }

    public function setUpButtons() : void
    {
        var backButton:Button = new Button();
        backButton.addEventListener( MouseEvent.CLICK, backClick );
        addChild( backButton );

        var forwardButton:Button = new Button();
        forwardButton.addEventListener( MouseEvent.CLICK, forwardClick );
        addChild( forwardButton );
    }

    private function backClick( e:Event ) : void
    {
        ParentClass( this.parent ).transitionForward();
    }

    private function forwardClick( e:Event ) : void
    {
        ParentClass( this.parent ).transitionBackward();
    }
}
Run Code Online (Sandbox Code Playgroud)

一方面,我觉得MenuClass与其父级绑定得太紧,因此不太可重复使用.另一方面,我觉得,为了保持一切自包含,ParentClass不负责进入MenuClass实例并在那里添加事件监听器.这似乎应该有某种OOP经验法则来管理这种关系.

所以我的问题是:我的MenuClass是否与其父级太紧密了?如果是这样,你有什么建议可以放松这种耦合吗?

谢谢.

小智 5

如果您有任何机会想要提供多种导航方式(除了菜单之外),那么使用事件驱动方法是有道理的.它可以让你几乎完全将Parent与菜单分离.

这是我在Flash中实际测试过的一些代码.;)

父级创建菜单对象并从中侦听FORWARD和BACKWARD事件:

package  
{
        import flash.display.Sprite;
        import flash.events.Event;

        public class ParentClass extends Sprite
        {
            public function ParentClass() 
            {
                setupOptionMenu();
            }

            private function setupOptionMenu() : void
            {
                var myMenu:MenuClass = new MenuClass;
                myMenu.setUpButtons();
                this.addChild( myMenu );

                myMenu.addEventListener(MenuClass.FORWARD, transitionForward);
                myMenu.addEventListener(MenuClass.BACKWARD, transitionBackward);
            }

            public function transitionForward(e:Event) : void
            { 
                trace("forward");
            }

            public function transitionBackward(e:Event) : void
            {
                trace("backward");
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

然后,当单击某些内容时,MenuClass将调度这些事件:

package  
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.display.SimpleButton;

        public class MenuClass extends Sprite
        {
            public static const FORWARD:String = "forward";
            public static const BACKWARD:String = "backward";

            public function MenuClass() 
            {
                setUpButtons();
            }

            public function setUpButtons() : void
            {
                var rect:Sprite = new Sprite();
                rect.graphics.beginFill(0x666666);
                rect.graphics.drawRect(0,0,50,20);

                var backButton:SimpleButton = new SimpleButton(rect, rect, rect, rect);
                backButton.x = 10;
                backButton.y = 10;
                backButton.addEventListener( MouseEvent.CLICK, backClick );
                addChild( backButton );

                var forwardButton:SimpleButton = new SimpleButton(rect, rect, rect, rect);
                forwardButton.x = 70;
                forwardButton.y = 10;
                forwardButton.addEventListener( MouseEvent.CLICK, forwardClick );
                addChild( forwardButton );
            }

            private function backClick( e:MouseEvent ) : void
            {
                dispatchEvent(new Event(BACKWARD));
            }

            private function forwardClick( e:MouseEvent ) : void
            {
                dispatchEvent(new Event(FORWARD));
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

要提供备用UI方法,例如键盘快捷键或上下文菜单等,只需调度相同的FORWARD和BACKWARD事件,并让Parent也听取它们.您也可以创建一个新的Event子类,并根据需要将FORWARD和BACKWARD常量放在那里.