Интерфейс Observer и класс Observable

Интерфейс Observer определяет всего один метод, update (Observable o, Object arg), который вызывается, когда обозреваемый объект изменяется.

Класс Observable предназначен для поддержки обозреваемого объекта в парадигме MVC (model-view-controller), которая, как и другие проектные решения и шаблоны, описана в специальной литературе. Этот класс должен быть унаследован, если возникает необходимость в том, чтобы отслеживать состояние какого-либо объекта. Обозреваемый объект может иметь несколько обозревателей. Соответственно, они должны реализовать интерфейс Observer.

После того, как в состоянии обозреваемого объекта что-то меняется, необходимо вызвать метод notifyObservers, который, в свою очередь, вызывает методы update у каждого обозревателя.

Порядок, в котором вызываются методы update обозревателей, заранее не определен. Реализация по умолчанию подразумевает их вызов в порядке регистрации. Регистрация осуществляется с помощью метода addObserver(Observer o). Удаление обозревателя из списка выполняется с помощью deleteObserver(Observer o). Перед вызовом notifyObservers необходимо вызвать метод setChanged, который устанавливает признак того, что обозреваемый объект был изменен.

Рассмотрим пример организации взаимодействия классов:

public class TestObservable extends java.util.Observable { private String name = ""; public TestObservable(String name) { this.name = name; } public void modify() { setChanged(); } public String getName() { return name; } } public class TestObserver implements java.util.Observer { private String name = ""; public TestObserver(String name) { this.name = name; } public void update(java.util.Observable o,Object arg) { String str = "Called update of " + name; str += " from " + ((TestObservable)o).getName(); str += " with argument " + (String)arg; System.out.println(str); } } public class Test { public Test() { } public static void main(String[] args) { Test test = new Test(); TestObservable to = new TestObservable("Observable"); TestObserver o1 = new TestObserver("Observer 1"); TestObserver o2 = new TestObserver("Observer 2"); to.addObserver(o1); to.addObserver(o2); to.modify(); to.notifyObservers("Notify argument"); } }Пример 14.13.

В результате работы на консоль будет выведено:

Called update of Observer 2 from Observable with argument Notify argument Called update of Observer 1 from Observable with argument Notify argumentПример 14.14.

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

Коллекции

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

Массивы существовали в Java изначально. Кроме того, было определено два класса для организации более эффективной работы с наборами объектов: Hashtable и Vector. В JDK 1.2 набор классов, поддерживающих работу с коллекциями, был существенно расширен.

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

Классы, обеспечивающие манипулирование коллекциями объектов, объявлены в пакете java.util.

Интерфейсы

Интерфейс Collection

Данный интерфейс является корнем всей иерархии классов-коллекций. Он определяет базовую функциональность любой коллекции - набор методов, которые позволяют добавлять, удалять, выбирать элементы коллекции. Классы, которые реализуют интерфейс Collection, могут содержать дубликаты и пустые ( null ) значения.

AbstractCollection, как абстрактный класс, служит основой для создания конкретных классов коллекций и содержит реализацию некоторых методов, определенных в интерфейсе Collection.


Интерфейс Set

Классы, которые реализуют этот интерфейс, не допускают наличия дубликатов. В коллекции этого типа разрешено наличие только одной ссылки типа null. Интерфейс Set расширяет интерфейс Collection, таким образом, любой класс, имплементирующий Set, реализует все методы, определенные в Collection. Любой объект, добавляемый в Set, должен реализовать метод equals, чтобы его можно было сравнить с другими.

AbstractSet, являясь абстрактным классом, представляет собой основу для реализации различных вариантов интерфейса Set.


Интерфейс List

Классы, реализующие этот интерфейс, содержат упорядоченную последовательность объектов (объекты хранятся в том порядке, в котором они были добавлены). В JDK 1.2 был переделан класс Vector, так, что он теперь реализует интерфейс List. Интерфейс List расширяет интерфейс Collection, и любой класс, имплементирующий List, реализует все методы, определенные в Collection, и в то же время вводятся новые методы, которые позволяют добавлять и удалять элементы из списка. List также обеспечивает ListIterator, который позволяет перемещаться как вперед, так и назад по элементам списка.

AbstractList, как абстрактный класс, представляет собой основу для реализации различных вариантов интерфейса List.

Интерфейс Observer и класс Observable - student2.ru

Рис. 14.1.

Основные типы для работы с коллекциями.


Интерфейс Map

Классы, которые реализуют этот интерфейс, хранят неупорядоченный набор объектов парами ключ/значение. Каждый ключ должен быть уникальным. Hashtable после модификации в JDK 1.2 реализует интерфейс Map. Порядок следования пар ключ/значение не определен.

Интерфейс Map не расширяет интерфейс Collection. AbstractMap, будучи абстрактным классом, представляет собой основу для реализации различных вариантов интерфейса Map.


Интерфейс SortedSet

Этот интерфейс расширяет Set, требуя, чтобы содержимое набора было упорядочено. Такие коллекции могут содержать объекты, которые реализуют интерфейс Comparable, либо могут сравниваться с использованием внешнего Comparator.


Интерфейс SortedMap

Этот интерфейс расширяет Map, требуя, чтобы содержимое коллекции было упорядочено по значениям ключей.


Интерфейс Iterator

В Java 1 для перебора элементов коллекции использовался интерфейс Enumeration. В Java 2 для этих целей должны применяться объекты, которые реализуют интерфейс Iterator. Все классы, которые реализуют интерфейс Collection, должны реализовать метод iterator, который возвращает объект, реализующий интерфейс Iterator. Iterator весьма похож на Enumeration, с тем лишь отличием, что в нем определен метод remove, который позволяет удалить объект из коллекции, для которой Iterator был создан.

Таким образом, подводя итог, перечислим интерфейсы, используемые при работе с коллекциями:

java.util.Collection java.util.Set java.util.List java.util.Map java.util.SortedSet java.util.SortedMap java.util.Iterator

Наши рекомендации