2010-02-07 72 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

相關問題