GUI Pattern Вопрос: PropertyChangeListener против Специализированного интерфейса представления - PullRequest
0 голосов
/ 11 апреля 2009

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

Я не разрабатываю для конкретной структуры GUI. Целью здесь является возможность поменять различные интерфейсы графического интерфейса пользователя (прямо сейчас для тестирования, но может быть полезно позже для разных версий приложения). Это может быть Swing или веб-браузер (например, через GWT).

Ниже мой подход. Представление реализует интерфейс для предоставления метода для обновления. Это запускается контроллером, когда он определяет, что он обновил модель. Это все еще хорошо для меня, поскольку контроллер взаимодействует только с представлением через модель, контроллер не зависит от конкретной реализации представления.

Итак, я думаю, мой вопрос (ы):

  • это хорошо работает?
  • Это стандартная практика?
  • У этого шаблона есть имя?

Пример грубого кода (Java):

// Controller, manages Items (the model)
class ItemList {

   void addItem(Item item) {
   }

   void doStuffWithItems() {

     // perform some set of operations, such as sorting or layout
     for (Item item : items) {
       // ....
     }

     // now with everything in it's final position:
     for (Item item : items) {
       item.updateView();
     }
   }
}

// Model
class Item {
  private int top;
  private int left;
  private int width;
  private int height;

  // Can remember it's previous position/size:
  public void savePostion() {
  }

  // And recall it for the Controller to use:
  public public Position getSavedPosition() {
  }

  // Plus some other useful functions:
  public boolean intersectsWith(Item other) {

  }

  public void updateView() {
    this.view.update();
  }

  void setView(ItemView view) {
    this.view = view;
  } 
}

// Interface used by View implementations
public interface ItemView {
  // Trigger the view to reflect the current state of the model
  void update();
}

// Example, as a Swing component
class ItemComponent extends JComponent implements ItemView {
  private Item item;

  public ItemComponent(Item item) {
    this.item = item;
    item.setView(this);
  }

  // ItemView#update
  public void update() {
    // update the component's size/position
    setBounds(new Rectangle(item.getLeft(), item.getTop(), item.getWidth(), item.getHeight()));
  }

  @Override
  public void paint(Graphics g) {
    // ...
  }
}

Ответы [ 3 ]

2 голосов
/ 11 апреля 2009

Я бы не заставлял View реализовывать интерфейс только для уведомления об изменениях. Вместо этого создайте отдельное событие «обновить сейчас» для модели.

0 голосов
/ 11 апреля 2009

Для традиционных приложений, которые запускаются на рабочем столе компьютера, я рекомендую варианты Passive View . Класс, отвечающий за создание и управление формой, представляет собой тонкую оболочку, которая передает события в объект пользовательского интерфейса. UI_Object взаимодействует с формой через интерфейс. Термин UI Object реализует интерфейс UI_View и регистрируется в View Controller, который расположен ниже в иерархии объектов.

Затем UI_Object выполняет объект, реализующий Шаблон команды , который модифицирует модель. Командный объект может взаимодействовать с различными представлениями через интерфейсы, предоставляемые элементом управления представлением.

Это позволяет вам разорвать классы форм и заменить их классами-заглушками, которые реализуют интерфейсы форм. Классы-заглушки используются для автоматического тестирования, особенно для интеграционных тестов.

Интерфейсы точно определяют взаимодействие между формой, UI_Object, командами и представлениями. Они могут быть разработаны так, чтобы быть относительно независимыми от языка, чтобы облегчить перенос между платформами.

В вашем примере вам не хватает командных объектов. Вам нужна эта структура

  • ItemViewForms
  • ItemViewImplementation
  • ItemViewFormInterface
  • ItemViewCommands
  • ItemViewInterface
  • MyModel

Включение ItemList в ItemViewImplementation

ItemComponent будет регистрироваться в ItemViewImplementation с использованием ItemViewInterface.

Последовательность событий будет выглядеть примерно так

  • Пользователь хочет обновить элемент
  • Клики по пользовательскому интерфейсу (при условии, что пользовательский интерфейс включает в себя щелчок мышью)
  • Форма сообщает ItemViewImplementation через ItemViewInterface, что X был сделано с параметрами Y.
  • ItemViewImplementation затем создает объект команды с необходимые параметры от Y.
  • Командный объект взять Y Параметры изменяет модель и затем говорит
  • ItemViewImplementation через ItemViewInterface для обновления пользовательского интерфейса.
  • ItemViewImplementation сообщает ItemViewForms для обновления пользовательского интерфейса через ItemViewFormInterface.
  • Обновление ItemViewForms.

Преимущество этого подхода состоит в том, что взаимодействие каждого уровня точно определяется через интерфейсы. Программные ДЕЙСТВИЯ локализованы в объектах команд. Слои формы ориентированы на отображение результата. Уровень View отвечает за маршрутизацию действий и ответов между командами и формами. Команды - единственное, что изменяет модель. Кроме того, у вас есть преимущество в том, чтобы отрывать реализацию форм для замены любого пользовательского интерфейса, который вы хотите, включая фиктивный объект для модульного тестирования.

0 голосов
/ 11 апреля 2009

Модель не должна контролировать или знать о представлении напрямую. Представление должно зарегистрировать обратный вызов с контроллером, чтобы контроллер мог сказать представлению, когда обновлять, поэтому его контроллер. Вы можете иметь модель, разрешающую внешних слушателей для modelChangedEvent. Тогда представление может быть зарегистрировано моделью в этом отношении, при этом модель не знает, что представление существует. См. План J2EE для MVC и описание косвенного уведомления об изменении состояния в модели.

...