I aim to understand pull model MVC. I'm stuck at defining a model for a simple color-guessing game in Java Swing I chose to practice it.
I borrowed the model's initial version from an example which was very simple:
class Model extends Observable {
private static final Random rnd = new Random();
private static final Piece[] pieces = Piece.values();
private Piece hidden = init();
private Piece init() {
return pieces[rnd.nextInt(pieces.length)];
}
public void reset() {
hidden = init();
setChanged();
notifyObservers();
}
public void check(Piece guess) {
setChanged();
notifyObservers(guess.equals(hidden));
}
}
enum Piece {
Red(Color.red), Green(Color.green), Blue(Color.blue);
public Color color;
private Piece(Color color) {
this.color = color;
}
}
The initial model seems great and does the minimum necessary to play the game. With the caveat that it is the so-called push model and thus observable, so the view registers itself as an observer of the model and is notified when it changes. It is also not named properly (although I'm not sure how should I name it, I attempted to call it GameLogic
).
I want to implement a pull model version of MVC, in which the View asks the model for its state in order to update itself. So I assume the model will have at least one getter for the View to retrieve that information. Actually I believe it will have more, for retrieving all the possible pieces in order to paint the choice buttons. The gameplay will become more complicated as well, I guess, with the view setting a given choice (throughout the controller) and asking the model if the game was won. A boolean check(Piece guess)
method seemed more suitable but separating it into two methods void setGuess(Piece guess)
and boolean won()
worked better for the MVC implementation.
What would be the proper modeling for this case?
I'm stuck in one more part, which is how the View will send its position (or rather its piece or color) to the model. I'd appreciate any help on that too. Because from my understanding the view does not hold state.
This is what I came up with. I stopped using an enum
(turned it into a Piece
class for extensibility) and got stuck at the following model:
public class GameLogic {
private static final Random RANDOM_NUMBER_GENERATOR = new Random();
private final Piece [] pieces;
private Piece hidden = createRandomPiece();
private Piece guess = null;
public GameLogic(Piece [] pieces) {
this.pieces = Objects.requireNonNull(pieces);
}
private Piece createRandomPiece() {
return pieces[RANDOM_NUMBER_GENERATOR.nextInt(pieces.length)];
}
public void reset() {
hidden = createRandomPiece();
}
public Piece getGuess() {
return guess;
}
public Piece [] getPieces() {
return Arrays.copyOf(pieces, pieces.length);
}
public void setGuess(Piece guess) {
this.guess = guess;
}
public boolean won() {
return guess.equals(hidden);
}
public Piece getPieceAtPosition(int position) {
if (position < 0 || position >= pieces.length) {
return null;
}
return pieces[position];
}
}
Was the original model okay (except for being push model MVC)? The model now seems to depend a lot on the View's requirements, this seems wrong to me. But for either push model or pull model the model will have to satisfy the View somehow.