Шаблон наблюдателя: что делает шаблон проектирования наблюдателя?

При программировании программного обеспечения важно учитывать целый ряд аспектов: Конечный продукт должен не только обладать желаемыми функциями, но и иметь легко воспроизводимый исходный код, который должен быть максимально читаемым. В то же время, объем работы должен быть как можно меньше — особенно когда разрабатываются программы или разделы программ с часто повторяющимися функциями или элементами. Используя так называемые паттерны GoF («банда четырех»), существует целый ряд предопределенных шаблонных решений для различных проблем в проектировании программного обеспечения.

Помимо других известных паттернов, таких как паттерн посетителя или паттерн синглтона, паттерн наблюдателя входит в эту коллекцию практических паттернов проектирования. При применении они значительно упрощают работу программиста. Мы объясним, что может делать паттерн наблюдателя, представим его на диаграмме UML и расскажем о сильных и слабых сторонах этого паттерна.

Что такое шаблон наблюдателя?

Шаблон проектирования наблюдателя — часто сокращаемый до шаблона наблюдателя — является одним из самых популярных шаблонов для проектирования компьютерного программного обеспечения. Он обеспечивает последовательный способ определения зависимости один-к-одному между двумя или более объектами для того, чтобы максимально быстро и просто передать все изменения, внесенные в определенный объект. Для этого любые объекты, выступающие в данном случае в роли наблюдателя, могут зарегистрироваться у другого объекта. Последний объект — называемый субъектом — информирует зарегистрированных наблюдателей, как только он изменился.

Как уже упоминалось в начале, паттерн наблюдателя является одним из паттернов GoF, опубликованных в книге «Design Patterns: Elements of Reusable Object-Oriented Software» в 1994 году. Более 20 описанных паттернов для проектирования программного обеспечения продолжают играть важную роль в проектировании и разработке компьютерных приложений.

Назначение и функции паттерна наблюдателя

Паттерн проектирования «Наблюдатель» работает с двумя типами действующих лиц: С одной стороны, есть субъект — то есть объект, за состоянием которого необходимо наблюдать в течение длительного времени. С другой стороны, есть наблюдающие объекты (наблюдатели), которые хотят получать информацию о любых изменениях в состоянии объекта.

Факт

Субъект обычно назначается нескольким наблюдателям. Однако, в принципе, модель наблюдателя можно использовать и для одного объекта наблюдения.

Без использования паттерна наблюдателя наблюдающие объекты должны были бы регулярно запрашивать у субъекта обновления статуса; каждый отдельный запрос был бы связан с соответствующим вычислительным временем, а также с необходимыми аппаратными ресурсами. Основная идея шаблона наблюдателя заключается в том, чтобы централизовать задачу информирования в пределах субъекта. Поэтому он ведет список, в котором наблюдатели могут зарегистрироваться, чтобы присоединиться к нему. В случае изменений субъект информирует зарегистрированных наблюдателей — одного за другим — без необходимости предпринимать какие-либо действия самостоятельно. Если автоматическое обновление статуса для определенного объекта-наблюдателя больше не требуется, его можно просто удалить из списка.

Примечание

Для информирования отдельных наблюдателей доступны два различных метода. При использовании метода push объект передает измененный статус вместе с уведомлением. Однако это может привести к проблемам, если будет отправлена информация, которую наблюдатель не сможет использовать. Эта проблема не возникает при использовании альтернативного метода вытягивания. При таком подходе субъект просто направляет информацию о том, что произошли изменения. Затем наблюдатели должны запросить измененный статус с помощью отдельного запроса метода.

Представление модели наблюдателя на диаграмме UML

Посторонним людям часто бывает трудно понять функции и преимущества паттернов проектирования, таких как паттерн наблюдателя. Чтобы улучшить понимание, неплохо представить паттерн проектирования в графической форме. В частности, широко распространенный язык моделирования UML (Unified Modeling Language) хорошо подходит для этой цели, поскольку он наглядно визуализирует зависимости как для пользователей, так и для прикладных экспертов. Следующая абстрактная диаграмма показывает модель наблюдателя в UML.

Каковы преимущества и недостатки паттерна проектирования «Наблюдатель»?

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

Но тот факт, что субъект автоматически информирует всех зарегистрированных наблюдателей о любых изменениях, не всегда является преимуществом. В конце концов, информация об изменениях отправляется даже в том случае, если она неактуальна для одного из наблюдателей. Это может иметь негативный эффект, если число зарегистрированных наблюдателей очень велико, поскольку в этом случае система наблюдателей может тратить огромное количество вычислительного времени. Еще одна проблема с паттерном проектирования наблюдателя заключается в том, что в исходном коде субъекта часто не видно, каким наблюдателям должна быть предоставлена информация.

Шаблон наблюдателя: где он используется?

Паттерн проектирования «Наблюдатель» используется в приложениях, основанных на компонентах, состояние которых:

  • с одной стороны, тщательно отслеживается другими компонентами, а с другой;
  • с другой стороны, подвержено регулярным изменениям.

Типичные случаи применения включают графические пользовательские интерфейсы (GUI), которые предоставляют пользователям простой в использовании интерфейс для взаимодействия с программным обеспечением. Как только данные изменяются, эти изменения должны быть обновлены во всех компонентах GUI — сценарий, идеально охватываемый структурой субъект/наблюдатель паттерна наблюдателя. Даже программы, которые работают с наборами данных, подлежащих визуализации (будь то классические таблицы или графические диаграммы), также выигрывают от структуры паттерна проектирования.

Что касается используемого языка программирования, то для паттерна проектирования «Наблюдатель» в принципе не существует особых ограничений. Важно лишь, чтобы поддерживалась объектно-ориентированная парадигма, чтобы реализация паттерна также имела смысл. Языки, в которых использование паттерна очень популярно, включают C#, C++, Java, JavaScript, Python и PHP.

Паттерн «Наблюдатель»: пример использования

То, как именно паттерн проектирования «Наблюдатель» реализуется в различных языках программирования, может существенно отличаться. Но основной принцип всегда один и тот же: определенный объект или его состояние становится более доступным для ряда других объектов. Практический пример можно найти в учебнике по паттерну наблюдателя на немецком сайте javabeginners.de, на который мы хотели бы здесь ориентироваться.

В этом примере текст, опубликованный субъектом, отображается в текстовых полях нескольких наблюдателей. Для этого класс subject расширяет класс observable методом addObserver(). Это позволяет добавлять наблюдателей. Кроме того, вводится метод setChanged(), который регистрирует изменения в субъекте и в случае изменений вызывает метод notifyObservers() для информирования всех наблюдателей.

class Subject extends Observable {
	public Subject(){
		this.addObserver(new Observer_1());
		this.addObserver(new Observer_2());
		tell("Text");
	}
	public void tell(String info){
		if(countObservers()>0){
			setChanged();
			notifyObservers(info);
		}
	}
}

Кроме того, наблюдателям необходима реализация интерфейса наблюдателя, включающая метод update() и два параметра: наблюдаемый объект и изменение в виде экземпляра объекта (ConcreteSubject).

class Observer extends JFrame implements Observer{
	private JTextField field;
	public Observer(){
		field1 = new JTextField("a");
		add(field);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(300, 50);
		setVisible(true);
	}
	public void update(Observable o, Object arg) {
		field.setText((String) arg);
	}
}

Оцените статью
cdelat.ru
Добавить комментарий