Эта рекурсия является признаком более общей проблемы проектирования. Вы, конечно, можете попытаться решить эту проблему путем «утечки» ссылки на экземпляр из конструктора или отложить «построение» на какой-либо метод инициализации, который вы вызовете позже (возможно, лениво), но я бы не рекомендовал этот 1.
Почему GUI и класс Player должны быть одиночными и должны знать друг о друге, а точнее, должны знать друг друга во время построения? Есть ли какая-то другая причина, кроме «Удобнее», иметь глобальный доступ к какому-либо объекту? Не то чтобы удобство было неважным, но обычно оно не должно быть единственной причиной дизайнерского решения.
Лучшим подходом было бы полностью избавиться от синглтонов, потому что нет реальной причины, по которой не может быть двух экземпляров Player и GUI одновременно. Конечно, у вас, вероятно, будет только по одному из них в вашей программе, но цель синглтонов не в этом.
Кроме того, у вас должна быть зависимость только в одном направлении. Попробуйте подумать о том, что может существовать без другого, а что нет. Я бы подумал, что графический интерфейс должен зависеть от проигрывателя, как вы, вероятно, могли представить себе проигрыватель без графического интерфейса, но графический интерфейс без проигрывателя вообще не имеет смысла. Итак, вы сначала создаете Player, а затем создаете графический интерфейс и передаете ему экземпляр Player, с которым он работает. Если вы думаете, что вам нужен доступ к вашему экземпляру графического интерфейса из любого места внутри Player, вам следует переосмыслить свой дизайн и попытаться сделать эти объекты более независимыми. Обычно это можно сделать с помощью шаблона Observer и позволить графическому интерфейсу отслеживать изменения / действия / прочее, что происходит. Таким образом, код вашего приложения вообще не знает о графическом интерфейсе пользователя. Однако внутри вашего графического интерфейса вы можете передавать экземпляры графического интерфейса сколько угодно.
Что касается идеи введения объекта «Менеджер» или паттерна «Фабрика»: это может быть полезно, но вы определенно можете сделать все, о чем я сказал выше, без этого и при этом иметь разумный дизайн. Я бы вообще был против классов «Менеджер», так как они, как правило, делают слишком много вещей и, как правило, являются своего рода замаскированным синглтоном. Фабрики, однако, могут быть полезны, но только в том случае, если вы хотите отделить фактическое построение вещей от их использования, например, чтобы позволить позже реализовать различные типы графических интерфейсов.
Итак, простая реализация будет выглядеть так:
public static void main(...) {
Player player = new Player();
// maybe some other stuff to configure/set up the player
GUI gui = new GUI(player);
gui.show(); // or something similar
}
Если вы хотите использовать фабрики, вы, конечно, можете заменить выражения new ...
обращениями к фабрикам, которые вам нужно было получить раньше.
1 Почему? Ну, например, что произойдет, если вы сконструируете графический интерфейс успешно, но позже не сможете его инициализировать, например выброшено исключение? Вам понадобится какой-то способ передать это «недействительное» состояние всем объектам, которые уже получили экземпляр GUI. Кроме того, вам нужно будет убедиться, что никто не использует экземпляр GUI до его инициализации.
person
Simon Lehmann
schedule
14.03.2013