Дублирование видимых данных.
Данные предметной области программы хранятся в классах, отвечающих за пользовательский интерфейс (GUI).
Имеет смысл выделить данные предметной области в отдельные классы и, таким образом, обеспечить связь и синхронизацию между классом предметной области и GUI.
##Example


##Why Refactor
Вы хотите иметь несколько видов интерфейса для одних и тех же данных (например, у вас есть приложение не только для десктопа, но также для телефонов и планшетов). В этом случае вам будет очень сложно избежать большого количества ошибок и дублирования кода, если вы не разделите GUI и предметную область.
##Benefits
-
Вы разделяете ответственность между классами бизнес-логики и представления (принцип единственной обязанности), что упрощает читабельность и понимание программы в целом.
-
Если потребуется добавить новый вид интерфейса, вам нужно будет создать новые классы представления, при этом код бизнес-логики трогать нет никакой нужды (принцип открытости/закрытости).
-
Над бизнес-логикой и пользовательскими интерфейсами теперь могут работать разные люди.
##How to Refactor
-
Необходимо скрыть прямой доступ к данным предметной области в классе GUI, для чего лучше всего использовать самоинкапсуляцию поля. Таким образом, вы создадите геттеры и сеттеры к этим данным.
-
В обработчиках событий класса GUI используйте сеттеры для установки новых значений полей. Это даст возможность передавать новые значения в связанный объект предметной области.
-
Создайте класс предметной области и скопируйте в него необходимые поля из класса GUI. Для всех этих полей создайте геттеры и сеттеры.
-
Примените паттерн Наблюдатель к этим двум классам:
-
В классе предметной области создайте массив для хранения объектов наблюдателей (объектов GUI), а также методы их регистрации, удаления и оповещения.
-
В классе GUI создайте поле для хранения ссылки на объект предметной области, а также метод
update(), который будет реагировать на изменения в этом объекте и обновлять значения полей в классе GUI. Обратите внимание, в методе обновления значения должны устанавливаться напрямую, чтобы избежать рекурсии. -
В конструкторе класса GUI создайте экземпляр класса предметной области и сохраните его в созданном поле. Зарегистрируйте объект GUI как наблюдатель в объекте предметной области.
-
В сеттерах полей класса предметной области вызывайте метод оповещения наблюдателя (т.е. метод обновления в классе GUI), чтобы передать новые значения в пользовательский интерфейс.
-
Измените сеттеры полей класса GUI так, чтобы они теперь устанавливали новые значения в объекте предметной области, причём напрямую. Будьте внимательны, если значения будут устанавливаться через сеттер класса предметной области, это приведёт к бесконечной рекурсии.
-