2010-02-07 76 views
4

在以下简单的情况下,你会如何坚持“告诉,不要问”的原则(以下简称“原则”)?在俄罗斯方块游戏,我有相关的以下示例局,BlockGrid和片类:如何在这个简单的例子中思考“告诉,不要问”?

public class Board 
{ 
    private var fallingPiece:Piece; 
    private var blockGrid:BlockGrid; 
    ... 
    public function moveFallingPiece(xDirection:int, yDirection:int):void 
    { 
     blockGrid.movePiece(fallingPiece, xDirection, yDirection); 
    } 
} 

一旦fallingPiece放置BlockGrid的底行,应该不再是“fallingPiece”。我是否正确,因为我没有违反以下原则?

if(blockGrid.getPiecePosition(piece).y == 0) 
{ 
    fallingPiece = null; 
} 

但是,这是真的不同于这,我认为这明显违反了原则?

public function moveFallingPiece(xDirection:int, yDirection:int):void 
{ 
    if(blockGrid.getPiecePosition(piece).y > 0) 
    { 
     blockGrid.movePiece(fallingPiece, xDirection, yDirection); 
    } 
    else 
    { 
     fallingPiece = null; 
    } 
} 

我并不假定我设计了这些类关系,以正确的方式来处理原则。如果这是我错过的,请就替代设计提供建议。


编辑,建议解决办法:

我去的答案提出通过事件 “命令反馈”。董事会告诉BlockGrid移动一块。 BlockGrid的movePiece方法根据结果分派MOVED_TO或MOVE_FAILED事件,该结果可由Board听取并用于确定棋子是否停止落下。请不要犹豫就此解决方案提供反馈。

public class Board 
{ 
    ... 
    public function Board() 
    { 
     ... 
     blockGrid.addEventListener(PieceMoveEvent.MOVE_FAILED, onPieceMoveFailed); 
     ... 
    } 

    public function moveFallingPiece(xDirection:int, yDirection:int):void 
    { 
      blockGrid.movePiece(fallingPiece, xDirection, yDirection); 
    } 

    public function onPieceMoveFailed(event:MovePieceEvent):void 
    { 
     if(event.instance == currentlyFallingPiece && event.fromPosition.y != event.toPosition.y) 
     { 
      currentlyFallingPiece = null; 
     } 
    } 
+0

怎么不问不说工作? – 2010-02-07 02:07:14

+0

这里有一个很好的参考“告诉,不要问”:http://www.pragprog.com/articles/tell-dont-ask – Dolph 2010-02-07 02:23:47

回答

1

我认为,更好地遵循出来,不问原则,你应该有blockGrid通知你的主板类时fallingPiece已经达到它的休息点。在上面的两种情况下,您要求blockGrid判断piece的位置.y == 0以确定fallingPiece是否应为null。相反,你希望blockGrid告诉board类fallPiece.y已经命中0.

+0

其实这些作品不应该有任何“逻辑”在其中,董事会应该告诉他们该做什么。 – 2010-02-07 02:17:39

0

我期望一个类表示每个形状(没有位置信息),一个控制器包含一个形状,位置和方向,另一个类表示当前产生的“落地”网格。在登陆网将有一个

testLanded(shape, shapePosition, orientation) 

方法,它会被称为前/后决定每一个移动操作如果形状是加入降落网格或应移动并保持为下降件。

我要去的到,不应该真正拥有的数据对象不给数据的想法 - 但我从来没有实现的俄罗斯方块......

+0

有趣,但是如何在不查询其他对象状态的情况下实现testLanded? – Stiggler 2010-02-08 07:17:49

+0

landedGrid可能会有一个前一个块已经着陆的二维数组 - 一个块在这一点上将不再是一个合适的块,而只是成为该网格中的一些颜色。因此,地面网格消耗块到自己的数据结构,所以它有所有的信息来判断当前块是否落在前面块留下的景观上 – DaveC 2010-02-14 11:39:09

1

你在找什么是事件驱动编程。您需要一个名为.event()和Event接口的Listener接口来表示事件。对象将向其他对象(回调)注册到监听器接口。

当你创建一个Piece和Board时,他们应该实现Listener接口。然后你可以使用registerListener(board)来设置板子;然后,当Piece内部发生事件时,它将循环所有注册的侦听器并在每个侦听器上调用.event(event)。与董事会一样,每次创建新作品时都会调用board.registerListener(piece),因为它决定发生的事情,它可以告诉所有注册的听众发生了什么。然后,您可以告诉董事会决定这件事的东西不再落下。这是义务维基百科entry

0

您可能需要重新考虑您的设计。董事会是否真的需要跟踪落下的棋子或属于BlockGrid的棋子?消除谁拥有什么行为。

保持你的Piece类的位置信息,并可能让你的Piece类持有BlockGrid的一个实例。

然后,您可以尝试在董事会类这样的事情...

public function moveFallingPiece(xDirection:int, yDirection:int):void 
{ 
    blockGrid.moveFallingPiece(xDirection, yDirection); 
} 
在BlockGrid的moveFallingPiece方法

则...

public function moveFallingPiece(xDirection:int, yDirection:int):void 
{ 
    fallingPiece.move(xDirection, yDirection); 
} 

在片中的移动方法,增加你的逻辑..

public function move(xDirection:int, yDirection:int):void 
{ 
    setPosition(xDirection, yDirection); 

    if (getPosition().y <= 0) 
    { 
     blockGrid.setFallingPiece(null); 
     // this can bubble up to Board if need be 
    } 
} 

不确定AS3的所有功能,但它在这里使用抽象是有意义的。 (即让你的Piece类取决于ITrackFallingPieces而不是BlockGrid,并使BlockGrid实现ITrackFallingPieces)。

祝你好运!

+1

谢谢,我很欣赏设计反馈!但是,我不知道它是否回答我的问题。从Piece内部调用blockGrid.setFallingPiece看起来就像封装很差。就设计而言,我决定不要在Piece上存储位置信息,因为这样可以让两个Pieces具有相同的位置。 BlockGrid旨在跟踪网格上的Piece位置(可能更好地命名为PieceGrid); “堕落”的概念似乎是一项责任太多。 – Stiggler 2010-02-08 06:58:49

+0

男人,我们在这里谈论的是俄罗斯方块游戏,而不是最新的实时NASA燃料平衡器。冷却。 – 2010-02-08 07:19:54

+0

该评论的目的是谁?我对这个问题的主要意图不是让俄罗斯方块游戏起作用,而是为了更好地理解设计原则...... – Stiggler 2010-02-08 18:34:15

相关问题