ОО Дизайн, открытый / закрытый принципиальный вопрос - PullRequest
7 голосов
/ 18 сентября 2008

Я некоторое время размышлял над этим вопросом объектно-ориентированного проектирования и не смог найти удовлетворительного решения, поэтому подумал, что я расскажу его здесь для некоторых мнений.

У меня есть класс Game , представляющий пошаговую настольную игру, мы можем предположить, что для целей этого вопроса он похож на Monopoly. В моем дизайне у меня есть класс Player , содержащий метод TakeTurn .

Игра проходит по всем Player s и вызывает метод TakeTurn, чтобы выполнить все необходимые действия для завершения хода. Я хочу, чтобы у меня было n игроков, и я могу установить произвольное количество игроков в компьютер. Поэтому я подумал о том, чтобы иметь класс HumanPlayer и класс ComputerPlayer , оба из которых происходят от Player.

Game знает только класс Player и просто вызывает метод TakeTurn для каждого Player по очереди. Моя проблема заключается в том, что объекты ComputerPlayer могут быть полностью автоматизированы, то есть, следуя примеру «Монополия», могут принять решение о покупке недвижимости с использованием некоторой части логики. Теперь, с объектом HumanPlayer , он должен получить данные от реального пользователя, например, чтобы иметь возможность купить свойство, что, по-видимому, подразумевает другой интерфейс и потенциально означает, что они не должны получать

Мне не удалось найти хорошее решение проблемы, если бы класс Game не знал явных реализаций различных классов Player в явном виде. В классе Game я всегда мог предположить, что когда-нибудь будут только люди и компьютерные игроки, и он эффективно закроет его для расширения, но это не похоже на хорошее ОО-программирование.

Любые мнения по этому вопросу будут оценены.

Ответы [ 9 ]

7 голосов
/ 18 сентября 2008

Я думаю, вы не должны позволять классу Game обрабатывать IO. таким образом, метод TakeTurn (блокирующий) скрывает от игрового поля средства реализации. он может использовать другие объекты для связи с пользователем.

Все, что касается класса Game, должно касаться состояния доски и хода. все игроки должны реализовать интерфейс одного игрока и скрыть все реализации от игры.

2 голосов
/ 14 сентября 2009

Вероятно, у меня не было бы двух классов HumanPlayer и ComputerPlayer, но был бы один класс Player, который настраивается во время создания с правильной стратегией ввода.

Способ, которым игрок получает информацию для определения своего хода в следующем ходу игры, - это только вещь, которая отличается (по крайней мере, от исходного описания проблемы), поэтому просто заключите ее в отдельный абстракция.

Каким бы ни был класс высокого уровня, который устанавливает игру, он также должен создавать два набора игроков (один человек, другой компьютер-симулятор) с соответствующей стратегией ввода для каждого, а затем просто отдавать эти объекты игрока объекту игры. , Класс Game будет вызывать только метод TakeTurn в указанном списке игроков для каждого нового хода.

2 голосов
/ 21 сентября 2008

Если игра управляет состоянием игры и , выполняя ввод / вывод, игра делает слишком много.

Вы хотите, чтобы игра была строго ориентирована только на правила и повороты и изменения состояния. Игра не знает, кто такой игрок; он только знает, что у него есть игроки.

Вы хотите, чтобы игроки изучали состояние игры и выполняли законные действия во время своих ходов.

Игроки-люди и Игра в целом оба имеют общий пакет ввода-вывода, который показывает состояние игры и запрашивает ввод у людей.

Вы можете эффективно использовать Java Observable, сделав пакет ввода-вывода Observer Игры. Таким образом, об изменениях игрового состояния сообщается в I / O для отображения или регистрации или обоих.

1 голос
/ 18 сентября 2008

Интерфейс, который Player представляет Game , ортогонален поведению производных Player классов.

Тот факт, что реализация TakeTurn варьируется в зависимости от конкретного типа объекта Player , не должен вызывать беспокойство.

1 голос
/ 18 сентября 2008

Вместо того, чтобы сообщать игровому классу, что есть только один человек, почему бы не позволить ему получить эти данные во время меню / инициализации игры? Если игроков больше, это можно решить с помощью некоторой формы ввода (выберите игроков в меню) до инициализации класса игры.

0 голосов
/ 10 марта 2009

Вместо Game класса, вызывающего TakeTurn для всех игроков, игроки должны вызвать TakeTurn on класс Game и класс Game должны проверяться, если правый игрок делает свой ход.

Это должно помочь решить проблему пользователя и компьютера игрока.

0 голосов
/ 18 сентября 2008

Я бы сказал, классу Game должно быть все равно, компьютерный игрок или человек-игрок. Всегда следует вызывать TakeTurn в следующем классе игрока. Если это человек-игрок, то класс Player несет ответственность за общение с пользователем и запрос его действий. Это означает, что он будет блокироваться, пока пользователь не решит. Поскольку обычно взаимодействие с пользовательским интерфейсом происходит в основном потоке приложения, важно только, чтобы блокировка TakeTurn не блокировала приложение в целом, иначе пользовательский ввод не может быть обработан, пока Game ждет TakeTurn .

0 голосов
/ 18 сентября 2008

Я не уверен, что это то, что вы хотите

public abstract class Player 
{
  int position;
  DecisionMaker decisionDependency;

  ...

  public void TakeTurn()
  {
    position += RollDice();
    GameOption option GetOptions(position);
    MakeDescion(option);
  }

  protected int RollDice()
  {
    //do something to get the movement
  }

  protected abstract void MakeDecision(GameOption option);

}

Public class ComputerPlayer : Player
{
  public ComputerPlayer()
  {
    decisionDependency = new AIDecisionMaker();
  }

  protected override void void MakeDecision(GameOption option)
  {
    decisionDependency.MakeDecision(option);
    //do stuff, probably delgate toan AI based dependency
  }
}

Public class HumanPlayer : Player
{
  public HumanPlayer()
  {
    decisionDependency = new UIDecisionMaker();
  }

  protected override void void MakeDecision(GameOption option)
  {
    decisionDependency.MakeDecision(option);
    //do stuff, probably interacting with the a UI or delgate to a dependency
  }
}
0 голосов
/ 18 сентября 2008

Я думаю, класс Game не должен беспокоиться о каких-либо реализациях классов Player, а также игнорирует пользовательский интерфейс.

Любой пользовательский ввод должен обрабатываться классом HumanPlayer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...