
- •Объявление и определение класса.
- •Конструкторы и деструкторы ( типы конструкторов и деструкторов)
- •Дружественные функции.
- •Пеpегpузка опеpаций ( синтаксис operator)
- •Статические компоненты класса.
- •Пространства имен.
- •Иерархия классов ( последовательность работы конструкторов и деструкторов )
- •Доступ к наследуемым компонентам
- •Виртуальные функции (когда применяются, форма вызова)
- •Шаблоны ( пример template)
- •Ввод-вывод в файл. Сохранение объектов в файле.
- •Обработка исключений (блоки try, throw, catch)
- •Использование классов при организации исключений. Иерархия исключений
- •Паттерны и их классификация
- •Абстрактная фабрика.
- •Наблюдатель.
- •Классификация типов данных.
- •Массивы и строки. Оператор foreach
- •Классы, создание объектов.
- •Методы класса и их параметры.
- •Свойства класса.
- •Наследование и виртуальные функции. Механизмы наследования
- •Классы – интерфейсы.
- •Производные классы
- •Методы - члены класса
- •Виртуальные методы
- •Делегаты.
- •Создаем собственный делегат
Абстрактная фабрика.
Паттерн Абстрактная фабрика (также известен как Kit(инструментарий)) - предоставляет интерфейс для создания семейств, связанных между собой, или независимых объектов, конкретные классы которых неизвестны. Паттерн относится к порождающим, так как связан с процессом создания объектов.Рассмотрим UML диаграмму шаблона:
Рассмотрим диаграмму на примере проектирования программы “Мир животных”, в которой мы хотим “упорядочить” всех животных живущих в Европе и Африке:
AbstractFactory (фабрика Континентов) - объявляет интерфейс для операций, создающих абстрактные объекты-продукты;
ConcreteFactory (фабрика для Африки, фабрика для Европы) - конкретная фабрика. Реализует операции, создающие конкретные объекты-продукты;
AbstractProduct (Хищник, Травоядный) - абстрактный продукт. Объявляет интерфейс для типа объекта-продукта;
Product (Лев, Волк, Бизон, Медведь) - конкретный продукт. Определяет объект-продукт, создаваемый соответствующей конкретной фабрикой. Реализует интерфейс Abstract Product;
Client (Мир животных(приложение)) - клиент. Пользуется исключительно интерфейсами, которые объявлены в классах AbstractFactory и AbstractProduct.
Таким образом в проектируемой программе, создавая(инстанцируя) конкретную фабрику (к примеру для Европы), мы можем создавать семейство объектов с похожим поведением (Волк - хищник, живущий в Восточной Европе или Заяц - травоядный с ценным мехом). При этом созданием объектов-продуктов занимается непосредственно сама фабрика, поэтому нам нужен только ее один экземпляр. Зацитирую бандитов:
Фабрики и их продукция - вот ключевые участники паттерна абстрактная фабрика. Этот паттерн может создавать семейства объектов, не инстанцируя классы явно. Применять его лучше всего, когда число и общий вид изготавливаемых объектов остаются постоянными, но между конкретными семействами продуктов имеются различия. Выбор того или иного семейства осуществляется путем инстанцирования конкретной фабрики, после чего она используется для создания всех объектов. Подставив вместо одной фабрики другую, мы можем заменить все семейство объектов целиком. В паттерне абстрактная фабрика акцент делается на создании семейств объектов, и это отличает его от других порождающих паттернов, создающих только один какой-то вид объектов.
Вот некоторые проблемы которые помогает решать этот паттерн:
- Задание имени класса привязывает вас к конкретной реализации, а не к конкретному интерфейсу. Это может осложнить изменение объекта в будущем. Чтобы уйти от такой проблемы, создавайте объекты косвенно. - Уход от аппаратной и программной зависимости - Если клиент «знает», как объект представлен, хранится или реализован, то при изменении объекта может оказаться необходимым изменить и клиента. Сокрытие этой информации от клиентов поможет уберечься от каскада изменений. - Уход от сильной связанности
Наблюдатель.
Реализация данного паттерна используется для наблюдения за состоянием объектов в системе. Если состояние объектов изменяется в процессе их жизненного цикла, то Наблюдатель оповещает другие части системы об этих событиях.
В данной статье я попытаюсь как можно проще и понятнее рассказать об этом паттерне и привести пример программного кода на Java, реализующего Observer. В каких случаях используется Наблюдатель?
*Если один объект должен передавать сообщения другим объектам, но при этом он не может или не должен знать об их внутреннем устройстве;
*В случае если при изменении одного объекта необходимо изменять другие объекты;
*Для предотвращения сильных связей между объектами системы;
*Для наблюдения за состоянием определенных объектов системы;
Наблюдаемый (observable) объект (а точнее субъект или subject) должен предоставлять интерфейс для регистрации и дерегистрации наблюдателей (listeners). Ну а сами наблюдатели должны как минимум обладать открытым методом через который и будет происходить оповещение об изменении состояния субъекта. Этот метод часто называют notify.
Так как наблюдателей может быть достаточно много, для упрощения работы с ними можно использовать коллекцию (collection of observers). Приблизительно такой код я использую в этом случае:
public interface Observer {
void objectCreated(Object obj);
void objectModified(Object obj);
}
class EmptyObserver implements Observer {
public void objectCreated(Object obj) { }
public void objectModified(Object obj) { }
}
class Observers<T extends Observer> extends ArrayList<T> {
public void notifyObjectCreated(Object obj) {
for (Iterator<T> iter = (Iterator<T>) iterator(); iter.hasNext();)
iter.next().objectCreated();
}
public void notifyObjectModified(Object obj) {
for (Iterator<T> iter = (Iterator<T>) iterator(); iter.hasNext();)
iter.next().objectCreated();
}
}
Класс EmptyObserver может быть полезен в случае если у Наблюдателя достаточно большое количество notify методов. Тогда используя анонимные классы можно с легкостью создавать необходимые нам “узкоспециализированные” наблюдатели (те, у которых реализовано ограниченное количество методов) на лету:
Observers observers = new Observers();
observers.add(new EmptyObserver() {
public void objectCreated(Object obj) { /* реализация */ }
});
Далее, экземпляр класса Observers помещается в субъект за которым должно вестись наблюдение. Во всех местах кода, где происходит интересующее нас действие с классом-субъектом, добавляем соответствующий вызов notify метода у коллекции наблюдателей:
public class Subject {
Observers observers = new Observers();
private Object field;
public void setField(Object o) {
field = o;
observers.notifyObjectModified(this);
}
}
Нюансы предлагаю обсуждать в комментариях.
Классический пример использования паттерна Observer - это классы из пакета Java Swing. В Swing паттерн Наблюдатель используется для организации слабой взаимозависимости между моделью и графическими объектами. Методы notify вызываются при изменении значений свойств модели и передают информацию в виджеты. Кстати, очень рекомендую всем посмотреть исходный код Java Swing. Это действительно очень качественно спроектированная библиотека.