I'm trying to design the classes for the Wheel of Fortune game in Java. The below diagram represents the classes and the interaction between them.
. Below is the partial implementation of it. I appreciate some feedback on my design and approach. I'm mainly interested in classes and their dependencies. In code I referred MoneyPrize as DollarAmountSpinOutcome.
1) Is Wheel dependency on Player correct? If not how can I redesign to avoid it?
2) In method WheelOfFortune.getSpinOutcomeProcessor(SpinOutCome outcome) I am explicitly casting it to Specific spin out come. Is it a smell. Does it indicate a broken modeling?
public class WheelOfFortune { private List<Player> players; private Host host; private Wheel wheel; public WheelOfFortune(List<Player> players, Host host, Wheel wheel) { this.players = players; this.host = host; this.wheel = wheel; } public static void main(String[] args) { Player player1 = new Player("player1", new Account()); Player player2 = new Player("player2",new Account()); Player player3 = new Player("player3",new Account()); ArrayList<Player> players = new ArrayList<Player>(); players.add(player1); players.add(player2); players.add(player3); Host host = new Host(); Wheel wheel = new Wheel(); WheelOfFortune wheelOfFortune = new WheelOfFortune(players, host, wheel); wheelOfFortune.start(); } public void start() { int round = 0; while (!isGameOver()) { round++; for (Player player : players) { boolean isTurnOver = false; while (!isTurnOver) { Choice choice = player.makeChoice(); if (choice == Choice.SPIN_WHEEL) { SpinOutCome spinOutCome = player.spinWheel(wheel, round); isTurnOver = processSpinOutCome(spinOutCome); } else if (choice == Choice.BUY_VOWEL) { Character character = player.buyVowel(); isTurnOver = processOvalBuy(character); } } } } } private static boolean processVowelBuy(Character character) { return false; } private boolean processSpinOutCome(SpinOutCome spinOutCome) { SpinOutComeProcessor spinOutComeProcessor = getSpinOutcomeProcessor(spinOutCome); return spinOutComeProcessor.process(); } private SpinOutComeProcessor getSpinOutcomeProcessor(SpinOutCome spinOutCome) { if (spinOutCome instanceof DollarAmoutSpinOutcome) return new DollarAmoutSpinOutcomeProcessor(host, (DollarAmoutSpinOutcome) spinOutCome); else return null; } private static boolean isGameOver() { return false; } } Wheel
class Wheel { public SpinOutCome spin(Player player, int round) { // Return a random SpinOutcome; return new DollarAmoutSpinOutcome(player, 500, round); } } DollarAmoutSpinOutCome
class DollarAmoutSpinOutcome extends SpinOutCome { private Integer dollarAmount; public DollarAmoutSpinOutcome(Player player, int dollarAmount, Integer round) { super(player, round); this.dollarAmount = dollarAmount; } public Integer getAmount() { return dollarAmount; } } SpinOutCome
class SpinOutCome { protected Player player; protected Integer round; public SpinOutCome(Player player, Integer round) { this.player = player; this.round = round; } public Player getPlayer() { return player; } // DOLLAR_AMOUNT, LOSE_A_TURN, BANKRUPT, SOLVE_PUZZLE } Choice
enum Choice { SPIN_WHEEL, BUY_VOWEL, } Account
class Account { private Integer totalAmount; public void debit(Integer amount) { } public void credit(Integer ammount) { } } Host
class Host { public List<Integer> getCharacterOccurences(Character c) { return null; } public void uncoverConsonent(List<Integer> characterOccurences) { } } SpinOutComeLoseATurn
class SpinOutComeLoseATurn extends SpinOutCome { public SpinOutComeLoseATurn(Player player, Integer round) { super(player, round); } } SpinOutComeProcessor
class SpinOutComeProcessor { private Host host; private Player player; public SpinOutComeProcessor(Host host, Player player) { this.host = host; this.player = player; } public Host getHost() { return host; } public Player getPlayer() { return player; } public boolean process() { return false; } } Player
class Player { private Account account; private final String name; public Player(String name, Account account) { this.name = name; this.account = account; } public Choice makeChoice() { return null; } public Character guessConsonant() { return null; } public SpinOutCome spinWheel(Wheel wheel, int round) { return wheel.spin(this, round); } public String solvePuzzle() { return null; } public Character buyVowel() { return null; } public void acceptCashGift(Integer amount) { account.debit(amount); } } DollarAmoutSpinOutcomeProcessor
class DollarAmoutSpinOutcomeProcessor extends SpinOutComeProcessor { private DollarAmoutSpinOutcome dollarSpinOutCome; public DollarAmoutSpinOutcomeProcessor(Host host, DollarAmoutSpinOutcome dollarSpinOutCome) { super(host, dollarSpinOutCome.getPlayer()); this.dollarSpinOutCome = dollarSpinOutCome; } public boolean process() { boolean isTurnOver; Character character = getPlayer().guessConsonant(); List<Integer> characterOccurences = getHost().getCharacterOccurences(character); if (characterOccurences.size() > 0) { getPlayer().acceptCashGift(dollarSpinOutCome.getAmount() * characterOccurences.size()); getHost().uncoverConsonent(characterOccurences); isTurnOver = false; } else { isTurnOver = true; } return isTurnOver; } }