ConstructiCat Logo
CodeBust.
Browse section ▾

Дублирование видимых данных.

Problem

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

Solution

Имеет смысл выделить данные предметной области в отдельные классы и, таким образом, обеспечить связь и синхронизацию между классом предметной области и GUI.

##Example

До
Duplicate Observed Data - Before
После
Duplicate Observed Data - After

##Why Refactor

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

##Benefits

  • Вы разделяете ответственность между классами бизнес-логики и представления (принцип единственной обязанности), что упрощает читабельность и понимание программы в целом.

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

  • Над бизнес-логикой и пользовательскими интерфейсами теперь могут работать разные люди.

##How to Refactor

  1. Необходимо скрыть прямой доступ к данным предметной области в классе GUI, для чего лучше всего использовать самоинкапсуляцию поля. Таким образом, вы создадите геттеры и сеттеры к этим данным.

  2. В обработчиках событий класса GUI используйте сеттеры для установки новых значений полей. Это даст возможность передавать новые значения в связанный объект предметной области.

  3. Создайте класс предметной области и скопируйте в него необходимые поля из класса GUI. Для всех этих полей создайте геттеры и сеттеры.

  4. Примените паттерн Наблюдатель к этим двум классам:

    • В классе предметной области создайте массив для хранения объектов наблюдателей (объектов GUI), а также методы их регистрации, удаления и оповещения.

    • В классе GUI создайте поле для хранения ссылки на объект предметной области, а также метод update(), который будет реагировать на изменения в этом объекте и обновлять значения полей в классе GUI. Обратите внимание, в методе обновления значения должны устанавливаться напрямую, чтобы избежать рекурсии.

    • В конструкторе класса GUI создайте экземпляр класса предметной области и сохраните его в созданном поле. Зарегистрируйте объект GUI как наблюдатель в объекте предметной области.

    • В сеттерах полей класса предметной области вызывайте метод оповещения наблюдателя (т.е. метод обновления в классе GUI), чтобы передать новые значения в пользовательский интерфейс.

    • Измените сеттеры полей класса GUI так, чтобы они теперь устанавливали новые значения в объекте предметной области, причём напрямую. Будьте внимательны, если значения будут устанавливаться через сеттер класса предметной области, это приведёт к бесконечной рекурсии.