2015-04-14 3 views
2

Прошу простить мою паршивую терминологию!связь между классами в java

Я уже некоторое время борется с проблемой.

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

PARENT -> РЕБЕНОК -> Grandchild

где РОДИТЕЛИ владеют и строит ребенок, и так далее.

Теперь родитель имеет возможность делать вещи, которые должны выполнять как дети, так и дети. Допустим, что GRANDCHILD - это кнопка в графическом интерфейсе, а PARENT - игра CORE. Если кнопка нажата, я хочу приостановить игру. Кнопка/GRANDCHILD не имеет возможности сделать это сама, но нужно сделать это через PARENT/CORE.

РОДИТЕЛЕЙ -> РЕБЕНОК -> Grandchild + пауза игры() + что-то делать()

у меня есть три решения этой проблемы, ни один, который удовлетворяет меня.

  1. Возвращаемые значения. PARENT/GAME-CORE считает, что мышь нажата, звонит CHILD, который вызывает GRANDCHILD. GRANDCHILD подтверждает, что он был нажат и возвращает int или перечисление в PARENT/CORE. PARENT/CORE использует и case/if-else, чтобы определить, что нужно сделать.

РОДИТЕЛЕЙ INT: нажмите() -> РЕБЕНОК INT: нажмите() -> GRANCHILD INT: нажмите()

функция РОДИТЕЛЕЙ

switch(CHILD.click(){ 
case 1 do this; 
case 2: do that; 
etc. 
} 

Это решение, которое я ненавижу большинство. Мне не только нужно отслеживать ints/enums, но мне также нужно использовать switch/if-else, когда я могу использовать полиморфизм для получения более чистого кода.

  1. Я думаю, что этот метод называется обратным вызовом. По построению PARENT отправляет внутренний класс/набор функций, передаваемый в конструктор GRANDCHILD. GRANDCHILD сохраняет этот внутренний экземпляр класса и вызывает его методы, когда это необходимо.

    класс РОДИТЕЛЬ {

    детский ребенок;

    РОДИТЕЛЬ() { child = new CHILD (новый контроллер); }

    класс Controller {

    общественного аннулируются нажмите() { делать вещи ... }

    }

    }

Это нормально, но Безразлично Не чувствую себя хорошо. У gamecore могут быть сотни ДЕТЕЙ, и это означает сотню внутренних классов, функции которых могут делать более или менее то же самое.Занятия становятся огромными, когда игра растет. Это также создает циклы в иерархии, и я чувствую, что это плохо.

  1. Я думаю, что это называется «услуги». PARENT/GAMECORE является публичным. Любой класс может ссылаться на свои методы. Ну, в случае: PARENT-> CHILD-> GRANDCHILD, оба РОДИТЕЛЯ и РЕБЕНКА должны быть общедоступными, так как GRANDCHILD нуждаются как в методах ДЕТЕЙ, так и в РОДИТЕЛЯХ. Это не слишком хорошо.

Я мог бы жить с этим, если бы было только несколько классов, которые должны были быть доступны. Проблема в том, что мне нужно общение все время, почти все!

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

ответ

1

В основном это зависит от вашего стиля кодирования. Если вы посмотрите на некоторые игровые библиотеки, часто основные объекты ядра (ваше ядро, входные данные и т. Д.) Можно вызывать из любого места вашего кода, используя одиночные или другие шаблоны.

Если вы используете Java 1.8, вы можете использовать функцию обратного вызова без необходимости писать много внутренних классов.

//in your child/grandchild 
public void doStuff(Runnable callback){ 
    //do stuff 
    callback.run(); 
} 

И вы можете передать method references эти методы

//somewhere else 
child.doStuff(core::myCallbackFunction); 

Вы можете пройти много различных потребителей/поставщиков/функций таким образом, используя функциональные интерфейсы, так что вы можете также писать обратные вызовы с параметрами и возвращаемые значения.

Но, в основном, это зависит от того, что вы считаете лучшим/самым удобным для вас стилем кодирования.

+0

Значит, нет большой техники, которую я пропустил, что может освободить меня от моей тоски? – Jake

+0

Не так далеко, насколько я знаю. Другим возможным способом может быть передача какого-то основного объекта с помощью методов, и этот основной объект содержит «публичные» дети других основных объектов. Таким образом, вы избавитесь от одиночек. 'public void update (Core c) {c.Input.getInput(); ...}' – Loki

0

Одна вещь о вашем сообщении, которая немного запутывает, заключается в том, что здесь «родитель» и «дети» на самом деле не являются родителями и детьми в объектно-ориентированном смысле, а просто взаимодействуют с объектами. Таким образом, любая конкретная функциональность должна обрабатываться только соответствующим классом - нет необходимости привлекать другие объекты при передаче сообщения туда и обратно.

Для элементов GUI, таких как кнопки, рассмотрите возможность использования прослушивателей. Сделайте основной инструмент подходящим интерфейсом Listener и добавьте его к каждому из элементов - это шаблон проектирования Observer и несколько похож на подход обратного вызова.

+0

Это правда, PARENT -> CHILD -> GRANDCHILD по-прежнему является представлением в моем примере, но они связаны в этом смысле в другие способы, о которых я не упоминал. Однако проблема заключается в том, что PARENT, CHILD, GRANDCHILD все нуждается в доступе к «модели», и в свою очередь модель нуждается в некотором доступе к представлению (gui). Я запутался, но спасибо за подсказку !. – Jake

Смежные вопросы