Я откладывал реализацию уроков, полученных здесь, и у меня было достаточно времени, чтобы подумать о том, как правильно это сделать. Как говорили другие люди, четкое разделение, в котором у бэкэнд-объектов есть слушатели, когда их свойства меняются, определенно является подходящим способом. Мало того, что это решит конкретную проблему, о которой я спрашивал в этом вопросе, это заставит многие другие неприятные запахи дизайна в этом коде выглядеть лучше. На самом деле существует множество различных Backend-классов (по общим именам классов, которые я использовал в моем примере), каждый со своим собственным соответствующим классом Panel. И даже есть пара мест, где некоторые вещи можно перемещать, чтобы разделить другие пары классов на пары Backend / Panel, следуя той же схеме и уменьшая количество ненужной передачи в качестве параметров.
Остальная часть этого ответа будет зависеть от языка, так как я использую Java.
Я не очень беспокоился о «JavaBeans», но я обнаружил, что следующие базовые соглашения JavaBean были очень полезны для меня в прошлом: в основном, использование стандартных методов получения и установки для свойств. Оказывается, есть соглашение JavaBean, о котором я не знал, которое действительно поможет: связанные свойства. Связанные свойства - это свойства, доступные через стандартные методы получения и установки, которые запускают PropertyChangeEvents при их изменении. [Я не знаю точно, но стандарт JavaBeans может указывать, что все свойства должны быть «связанными свойствами». На данный момент не относится ко мне. Помните также, что «стандартные» методы получения и установки могут быть очень нестандартными из-за использования классов BeanInfo для определения точного интерфейса JavaBean, но я также никогда не использую это.] (Основное другое соглашение JavaBean, которому я хочу следовать или в каждой ситуации не уместен конструктор без аргументов, я уже следую за ним в этом проекте, потому что каждый из этих объектов Backend должен быть сериализуемым.)
Я нашел эту запись в блоге , которая очень помогла мне понять проблему связанных свойств / PropertyChangeEvents и помочь мне составить план того, как я собираюсь переработать этот код.
Сейчас все мои бэкэнд-объекты наследуются от общего класса Model, который обеспечивает несколько вещей, которые нужны каждому бэкенду в этой системе, включая поддержку сериализации. Я собираюсь создать дополнительный класс JavaBean как суперкласс Model, который обеспечит необходимую мне поддержку PropertyChangeEvent, унаследованную каждой Моделью. Я обновлю сеттеры в каждой модели, чтобы при вызове вызывать PropertyChangeEvent. У меня также может быть JavaBean, унаследованный парой классов, которые технически не являются моделями в том же смысле, что и эти, но которые также могут получить пользу от регистрации других классов в качестве слушателей для них. Класс JavaBean может не полностью реализовывать спецификацию JavaBean; как я уже сказал, есть несколько деталей, которые меня не волнуют. Но этого достаточно для этого проекта. Похоже, я мог бы получить все это, унаследовав от java.awt.Component, но это не компоненты в каком-то смысле, который я могу оправдать, поэтому я не хочу этого делать. (Я также не знаю, что это может повлечь за собой.)
После того, как каждая модель станет JavaBean, в комплекте с поддержкой PropertyChangeEvent, я сделаю много очистки кода: модели, которые в настоящее время хранят ссылки на панели, будут обновлены, и панели будут регистрироваться как слушатели. Так много чище! Модель не должна знать (и не должна знать в первую очередь), какие методы должна вызывать Panel при обновлении свойства.