Philosophical Design Questions for OOP-Tetris


You are writing a Tetris program in Java. How would you set up your class design with regards to the following aspects?

  • Piece class: Have one Piece class, with an internal array which determines the shape of the piece, versus having seven Piece classes, one for each of the pieces. They are all subclasses of one generic Piece class.
  • Piece class representation: Have an array of 4 instances of Block, representing one square of a piece, and each Block contains its location on the Board (in graphical coordinates) vs. having a 4×4 array where null means there is no block there, and location is determined by the shape of the array.
  • Location: Each Block in the Piece array or on the Board array stores its location vs. the Piece and the Board know the locations of the Blocks that comprise them.
  • Generating a Piece: Have a static method of the Piece class getRandomPiece, or have a PieceFactory which you make one instance of that has the genRandomPiece method on the instance.
  • Manipulating the current piece: Use the Proxy pattern, so that everything that needs access to it just uses the proxy, or have a getCurrentPiece method on the Board class and call that any time you want to do something with the current piece.

This is not homework. I'm just at odds with what the intro CS course teaches at my college and I want to see what people in general believe. What would be thought of as "good" OOP design? Ignore the fact that it's for an intro course – how would you do it?

Best Solution

Firstly, I wouldn't subclass the Piece class because it's unnecessary. The Piece class should be capable of describing any shape without using inheritance. IMHO, this isn't what inheritance was made for and it just complicates things.

Secondly, I wouldn't store the x/y coordinates in the Block objects because it allows two blocks to exist in the same place. The Piece classes would keep a grid (i.e. 2D array) holding the block objects. The x/y coordinates would be the indexes of the 2D array.

As for the static method vs factory object for getting a random piece, I'd go with the factory object for the simple fact that the factory object can be mocked for testing.

I would treat the board as one large Piece object. The Board class would keep the large Piece object as a member variable, and might keep other Piece objects such as the current piece being played, and the next piece to be played. This is done using composition to avoid inheritance.

Related Question