减少过多条件的最佳模式

Best pattern to reduce excessive conditionals

我有以下游戏代码,它通过随机决定一个项目来管理项目的显示模式,根据所选模式创建项目,然后为它们设置动画。

问题是由于规模庞大,清理代码和管理更改可能很麻烦,我最近一直在研究设计模式,我想知道哪一个最适合在这里应用,到目前为止我已经考虑过策略和命令作为可能的选项

"The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time." 看起来我可以用来根据所选模式应用项目的定位。

当被问及减少 if/elses 的数量时,通过查看之前的问题,命令模式出现了很多。

" 命令模式用于在命令对象中表达请求,包括要进行的调用及其所有必需的参数。命令可以立即执行或保留以备后用。"

不过,我不知道我是否可以在没有相关性的地方找到相关性,所以我想问问这样的模式是否可以应用于以下场景。

下面是相关代码,我特别有兴趣了解这个,因为几乎相同的代码被敌人重复了。

        /**
     * Set items pattern.  
     * 
     */

    private function setItemsPattern():void
    {
        // Change until enough flight distance has been accumulated.
        if (patternChange > 0)
        {
            patternChange -= playerSpeed * elapsed;
        }
        else
        {
            // As the player moves, change item patterns.

            if ( Math.random() < 0.7 )
            {
                // If  < normal item chance (0.7), get a random pattern.
                pattern = Math.ceil(Math.random() * 4); 
            }
            else
            {
                // If random number is > normal item chance (0.3), create special item.

                pattern = Math.ceil(Math.random() * 2) + 9;
            }

            if (pattern == GameConstants.ITEM_PATTERN_VERTICAL)  
            {
                // Vertical 
                patternStep = 15;
                patternChange = Math.random() * 500 + 500;
            }
            else if (pattern == GameConstants.ITEM_PATTERN_HORIZONTAL)
            {
                // Horizontal 
                patternOnce = true;
                patternStep = 40;
                patternChange = patternGap * Math.random() * 3 + 5;
            }
            else if (pattern == GameConstants.ITEM_PATTERN_ZIGZAG)
            {
                // ZigZag
                patternStep = Math.round(Math.random() * 2 + 2) * 10;
                if ( Math.random() > 0.5 )
                {
                    patternDirection *= -1;
                }
                patternChange = Math.random() * 800 + 800;
            }
            else if (pattern == GameConstants.ITEM_PATTERN_RANDOM)
            {
                // Random 
                patternStep = Math.round(Math.random() * 3 + 2) * 50;
                patternChange = Math.random() * 400 + 400;
            }
            else  
            {
                patternChange = 0;
            }
        }
    }

    /**
     * Creates items - called by createPattern() 
     * 
     */

    private function createItems():void
    {

        var itemToTrack:Item;

        switch (pattern)
        {
            case GameConstants.ITEM_PATTERN_HORIZONTAL:
                // Horizontal.
                if (Math.random() > 0.9)
                {
                    // Asignes items not too close to border.
                    patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;
                }


                itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
                this.addChild(itemToTrack);


                // Sets pos
                itemToTrack.x = stage.stageWidth + itemToTrack.width ;
                itemToTrack.y = patternPosY;

                // Marks item for animation
                itemsToAnimate.push(itemToTrack);


                break;

            case GameConstants.ITEM_PATTERN_VERTICAL:
                // Vertical
                if (patternOnce == true)
                {
                    patternOnce = false;


                    patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;


                    patternLength = (Math.random() * 0.4 + 0.4) * stage.stageHeight;
                }


                patternPosYstart = patternPosY; 


                while (patternPosYstart + patternStep < patternPosY + patternLength && patternPosYstart + patternStep < stage.stageHeight * 0.8)
                {


                    itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
                    this.addChild(itemToTrack);



                    itemToTrack.x = stage.stageWidth + itemToTrack.width;
                    itemToTrack.y = patternPosYstart;


                    itemsToAnimate.push(itemToTrack)


                    patternPosYstart += patternStep;
                }
                break;

            case GameConstants.ITEM_PATTERN_ZIGZAG:
                // ZigZag

                if (patternDirection == 1 && patternPosY > gameArea.bottom - 50)
                {
                    patternDirection = -1;
                }
                else if ( patternDirection == -1 && patternPosY < gameArea.top )
                {
                    patternDirection = 1;
                }

                if (patternPosY >= gameArea.top && patternPosY <= gameArea.bottom)
                {


                    itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
                    this.addChild(itemToTrack);


                    itemToTrack.x = stage.stageWidth + itemToTrack.width;
                    itemToTrack.y = patternPosY;


                    itemsToAnimate.push(itemToTrack)


                    patternPosY += patternStep * patternDirection;
                }
                else
                {
                    patternPosY = gameArea.top;
                }

                break;

            case GameConstants.ITEM_PATTERN_RANDOM:

                // Random, creates N amount of items on screen.
                if (Math.random() > 0.3)
                {

                    patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;


                    while (patternPosY + patternStep < gameArea.bottom)
                    {


                        itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
                        this.addChild(itemToTrack);


                        itemToTrack.x = stage.stageWidth + itemToTrack.width;
                        itemToTrack.y = patternPosY;


                        itemsToAnimate.push(itemToTrack)


                        patternPosY += Math.round(Math.random() * 100 + 100);
                    }
                }

                break;

            case GameConstants.ITEM_PATTERN_SPEED:

                // special item

                patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;


                itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_MANA);
                this.addChild(itemToTrack);


                itemToTrack.x = stage.stageWidth + itemToTrack.width;
                itemToTrack.y = patternPosY;


                itemsToAnimate.push(itemToTrack);

                break;

            case GameConstants.ITEM_PATTERN_STR:

            // special item

                patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;



                itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_REFERENCIA);
                this.addChild(itemToTrack);

                itemToTrack.x = stage.stageWidth + itemToTrack.width;
                itemToTrack.y = patternPosY;


                itemsToAnimate.push(itemToTrack);

                break;


        }
    }


    /**
     * Animates the vector itemsToAnimate. 
     * 
     */


    private function animateItems():void
    {

            var itemToTrack:Item;

            for(var i:uint = 0;i<itemsToAnimate.length;i++)
            {
                itemToTrack = itemsToAnimate[i];

                if (itemToTrack != null)
                {

                    if (referencia > 0 && itemToTrack.itemType <= GameConstants.ITEM_TYPE_REFERENCIA)
                    {

                        itemToTrack.x -= (itemToTrack.x - brujaX) * 0.2;
                        itemToTrack.y -= (itemToTrack.y - brujaY) * 0.2;


                    }
                    else
                    {

                        itemToTrack.x -= playerSpeed * elapsed; 
                    }


                    if (itemToTrack.x < -80 || gameState == GameConstants.GAME_STATE_OVER)
                    {
                        disposeItemTemporarily(i, itemToTrack);
                    }
                    else
                    {

                        brujaItem_xDist = itemToTrack.x - brujaX;
                        brujaItem_yDist = itemToTrack.y - brujaY;
                        brujaItem_sqDist = brujaItem_xDist * brujaItem_xDist + brujaItem_yDist * brujaItem_yDist;

                        if (brujaItem_sqDist < 5000)
                        {

                            if (itemToTrack.itemType == GameConstants.ITEM_TYPE_1)
                            {
                                scoreItems += itemToTrack.itemType;
                                hud.itemScore = scoreItems;
                                if (!Sounds.muted) Sounds.sndPag.play();
                            }

                            else if (itemToTrack.itemType == GameConstants.ITEM_TYPE_MANA) 
                            {

                                scoreItems += 1;


                                mana = 5;
                                if (isHardwareRendering) particleMana.start(mana);

                                if (!Sounds.muted) Sounds.sndMana.play();
                                if (!Sounds.muted) Sounds.sndRisa.play();
                            }

                            else if (itemToTrack.itemType == GameConstants.ITEM_TYPE_REFERENCIA) 
                            {

                                scoreItems += 1;

                                referencia = 20;
                                partRef = 0.5;
                                if (isHardwareRendering) particleRef.start(partRef);

                                playRandomRef();

                            }

                            if(referencia > 0){referencia--;}


                            disposeItemTemporarily(i, itemToTrack);
                        }
                    }
                }
            }
        }

您的函数 setItemsPattern 和 createItems 都包含一个 switch-case 语句,因此您可以创建一个基础 class 包含两个处理 switch-case 工作的函数。

例如,你得到这样的基础class

Class BaseBehavior
{

    //if the variable shouldn't be accessed by other class, change public to protected
    public var patternOnce:Boolean;

    public var patternStep:int;

    public var patternChange:int;

    public var patternDirection:int;

    public var itemToTrack:Object;

    public var gameArea:Object;

    //used in setItemsPattern function 
    public function initPatternData():void {};

   //used in createItems function 
    public function createItems():void {};

    public function dispose():void {};
}

这里是垂直的class

Class VerticalBehavior extends BaseBehavior
{

    override public function initPatternData():void
    {
          patternStep = 15;

          patternChange = Math.random() * 500 + 500;
    }

    override public function createItems():void 
    {
         if (Math.random() > 0.9)
         {
              // Asignes items not too close to border.
             patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;
         }

         itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);

         // Sets pos
         itemToTrack.x = stage.stageWidth + itemToTrack.width ;
         itemToTrack.y = patternPosY;
    }

}

其他子class大同小异

现在你需要一个工厂class来创建子class

 Class BehaviorFactory
 {

      public static function create(type:int):BaseBehavior
      {
           switch(type)
           {
              case 1://vertical
                  return new VerticalBehavior();

              case 2:
                  return ...

               ...
           }
      }
 }

完成这些工作后,您可以在旧逻辑代码中使用它们

private var behavior:BaseBehavior;

private function setItemsPattern():void
{
    if (behavior && behavior.patternChange > 0)
    {
        behavior.patternChange -= playerSpeed * elapsed;
    }
    else
    {
        // As the player moves, change item patterns.

        if ( Math.random() < 0.7 )
        {
            // If  < normal item chance (0.7), get a random pattern.
            pattern = Math.ceil(Math.random() * 4); 
        }
        else
        {
            // If random number is > normal item chance (0.3), create special item.

            pattern = Math.ceil(Math.random() * 2) + 9;
        }

        //here to create the sub class

        //dispose old behavior
        if (behavior)
        {
             behavior.dispose();
        }

        behavior = BehaviorFactory.create(pattern);

}


private function createItems():voidh
{
     //you may check behavior is null here
     var itemToTrack:Item = behavior.createItems();

      this.addChild(itemToTrack);

      // Marks item for animation
      itemsToAnimate.push(itemToTrack);
}

最后,如果你想添加一个新的类型,你只需要创建一个子行为class并将其添加到工厂class.But小心行为中的变量是否增加太多很多,你可能需要使用 composition class.