Software Design Паттерны проектирования. Продолжение Бреслав А. А. Facade – Фасад Задача: скрыть сложную структуру некоторой подсистемы, предоставив простой внешний API Решение: запретить доступ извне ко всем.
Download
Report
Transcript Software Design Паттерны проектирования. Продолжение Бреслав А. А. Facade – Фасад Задача: скрыть сложную структуру некоторой подсистемы, предоставив простой внешний API Решение: запретить доступ извне ко всем.
Software Design
Паттерны проектирования.
Продолжение
Бреслав А. А.
Содержание
Facade
Visitor
Prototype
Memento
Chain of Responsibility
Bridge
Другие
Mediator
Interpreter
Flyweight
Бреслав А. А.
Паттерны проектирования.
Продолжение
Facade – Фасад
Задача: скрыть сложную структуру
некоторой подсистемы, предоставив
простой внешний API
Решение: запретить доступ извне ко
всем классам, кроме тех, которые
обеспечивают API
Эти
классы (часто это один класс) и
образуют фасад
Бреслав А. А.
Паттерны проектирования.
Продолжение
Facade: реализация в Java
Подсистема локализуется в
пакете
внутренние элементы объявляются package-private
фасадные классы – public
бывают нужны фабрики для удобства создания
производства фасадных объектов
классе
Бреслав А. А.
подсистема состоит из inner-классов и закрытых методов
открытые методы образуют фасад
Паттерны проектирования.
Продолжение
Visitor – посетитель
Позволяет создавать полиморфные методы
вне классов
Добавить
функциональность, не загромождая
класс
Создать универсальный интерфейс для
расширения функциональности класса извне
Изменять реализацию методов во время
выполнения
Бреслав А. А.
Паттерны проектирования.
Продолжение
Visitor: пример
Есть некоторая модель (состоит из нескольких
классов)
Необходимо
Сохранять модель в файл
Загружать из файла
Рисовать на экране разными способами
Проверять корректность
…
Поместить все эти функции в классы модели (или
представления) – означает сильно смешать
ответственности
Бреслав А. А.
Паттерны проектирования.
Продолжение
Visitor: принцип работы
Создается интерфейс Visitor, содержащий методы для
обработки каждого класса модели
visitClass1(Class1 v)
visitClass2(Class2 v)
…
В общем базовом классе (интерфейсе) модели создается
диспетчерский метод
accept(Visitor v)
КАЖДЫЙ класс модели реализует этот метод
v.visitClass*(this)
этот метод нельзя не переопределять, поскольку реализация
родителя вызывает не ту версию посещающего метода
Для вызова операции на объекте o
o.accept(visitor)
Бреслав А. А.
Паттерны проектирования.
Продолжение
Visitor: использование
Для того, чтобы добавить новую операцию всем
классам иерархии, не смешивая ее с остальными
методами
Создать реализацию интерфейса Visitor, где каждый
посещающий метод реализует эту операцию для своего
класса
Вызов операции на объекте o
o.accept(visitor)
Вызов операции: двойная диспетчеризация
Вызывается метод accept истинного класса объекта o
Он вызывает посещающий метод, соответствующий этому
классу
Бреслав А. А.
Посещающий метод делает необходимую работу
Паттерны проектирования.
Продолжение
Visitor: реализация в Java
Можно использовать перегрузку
visit(Class1 o)
visit(Class2 o)
метод accept
Для обмена информацией с операцией, можно добавить
возвращаемое значение и параметр посещающим методам
interface Visitor<R, D> {
visitor.visit(this)
R visit(Class1 o, D data);
Часто полезно объявлять фасадные методы в классахреализациях
public R dispatch(ModelElement me) {
return me.accept(this);
Не всегда хорошо иметь открытые посещающие методы, часто
стоит объявить реализацию Visitor вложенным классом, а открыть
только фасадный метод
Бреслав А. А.
Паттерны проектирования.
Продолжение
Пример кода: арифметическое
выражение
Классы модели
Число
Сумма
Произведение
Внешние операции
Сохранение в двоичный поток
Загрузка из двоичного потока
Преобразование в инфиксную
Преобразование
Преобразование
Бреслав А. А.
запись
в ОПЗ
в словесную форму
Паттерны проектирования.
Продолжение
Visitor: заблуждение
Из-за не очень удачного примера в GoF
многие думают, что Visitor нужен только
для итерации по деревьям
Это
лишь частный случай использования
этого паттерна
модель является древовидной
внешняя операция осуществляет итерацию по
модели
Бреслав А. А.
Паттерны проектирования.
Продолжение
Prototype – Прототип
Задача: Создавать объекты по образцу,
который можно изменять во время
выполнения
Решение: Образцом является объект того же
класса – прототип
Примеры использования
Векторный
редактор: настройки фигур по
умолчанию
Шаблоны документов
Бреслав А. А.
Паттерны проектирования.
Продолжение
Prototype: реализация в Java
Для копирования объектов можно использовать
Cloneable
Конструктор копирования
стандартный механизм
плохо работает с наследованием
Нарушает принципы ООП: объекты создаются не конструктором
создает объект, в точности повторяющий существующий
может использоваться неявно через фабричный метод
Прототипы могут быть статическими константами
Бреслав А. А.
Паттерны проектирования.
Продолжение
Prototype: пример кода (1)
public interface Shape<T extends Shape> {
T copy();
}
public class Rect implements Shape<Rect> {
…
public Rect(Rect proto) {
…
}
public Rect copy() {
return new Rect(this);
}
}
Бреслав А. А.
Паттерны проектирования.
Продолжение
Prototype: пример кода (2)
public class ShapeFactory {
private final Rect rectProto;
private final Line lineProto;
public ShapeFactory(Rect rectProto, Line lineProto) {
this.rectProto = rectProto;
this.lineProto = lineProto;
}
public Line getLineProto() {
return lineProto;
}
public Rect getRectProto() { … }
public Line createLine() {
return lineProto.copy();
}
public Rect createRect() { … }
}
Бреслав А. А.
Паттерны проектирования.
Продолжение
Memento – Хранитель
Задача: сохранить текущее состояние
объекта так, чтобы потом его можно было
восстановить
Применение:
Сохранение настроек UI
расположение окон
содержимое строк ввода
Undo
Хранение
Бреслав А. А.
прототипов
Паттерны проектирования.
Продолжение
Memento – реализация в Java
Необходимо отдать наружу объект, хранящий
состояние, но не раскрывать структуру этого
состояния
Создается интерфейс Memento
методы
для сериализации
Класс, состояние которого нужно хранить
создает
inner-класс, реализующий Memento
умеет возвращать текущее состояние
умеет восстанавливаться из данного состояния
Бреслав А. А.
Паттерны проектирования.
Продолжение
Memento – пример кода
interface Memento { ... };
public static class ComplexState {
private static class MyMemento implements Memento {
// ...
}
private int state; // that complex state
public Memento getMemento() {
return new MyMemento(state);
}
public void restoreFromMemento(Memento memento) {
MyMemento myMemento = (MyMemento) memento;
state = myMemento.state;
}
}
Бреслав А. А.
Паттерны проектирования.
Продолжение
Memento: структурированное
хранилище
Создается единый интерфейс для
записи типизированных значений
DataOutputStream
или что-то похожее
Создаются методы для сохранения в
такое хранилище и загрузки из него
Бреслав А. А.
Паттерны проектирования.
Продолжение
Memento – пример кода
interface Memento {
void writeInt(int v);
void writeString(String v);
...
};
public static class ComplexState {
private int state; // that complex state
public void save(Memento memento) {
memento.writeInt(state);
}
public void restore (Memento memento) throws
WrongFormatException {
state = memento.readInt();
}
}
Бреслав А. А.
Паттерны проектирования.
Продолжение
Chain Of Responsibility – Цепочка
обязанностей
Задача: Есть некоторый запрос, который должен
обработать один из объектов. Заранее неизвестно,
какой…
Решение:
Выстроить объекты в цепочку
Передать запрос в начало цепочки
Если объект, получивший запрос, не может его обработать,
он передает его дальше
Пример
Загрузка классов в Java
ClassLoader’ы образуют дерево
Если ClassLoader не может загрузить класс, он просит об
этом своего родителя
Бреслав А. А.
Паттерны проектирования.
Продолжение
Chain Of Responsibility –
реализация в Java
Обычно сочетается с композитной
структурой моделей
Или
каким-либо делегированием, как
ClassLoader
Часто опрос цепочки идет рекурсивно
Бреслав А. А.
Паттерны проектирования.
Продолжение
Chain Of Responsibility: пример
кода
public interface Request { … }
public interface Processor {
Result process(Request request);
}
public class ProcessorInChain {
private final Processor parent;
public Result process(Request request) {
// try to process
// if failed
…
return parent.process(request);
}
}
Бреслав А. А.
Паттерны проектирования.
Продолжение
Bridge – Мост
Задача: Интерфейсы классов образуют
сложную иерархию наследования, а их
реализации – другую сложную
иерархию наследования.
В
Java это еще и способ эффективной
замены множественного наследования
Решение: Разделить в каждом классе
интерфейс и реализацию
Бреслав А. А.
Паттерны проектирования.
Продолжение
Bridge: пример
Используют API класса
WindowImpl
Бреслав А. А.
Для создания конкретных реализаций
используется AbstractFactory
Паттерны проектирования.
Продолжение
Оставшиеся три паттерна
Mediator – Посредник
Уменьшает
зависимости между классами, вводя
класс-посредник
Interpreter – Интерпретатор
Шаблон
для реализации интерпретаторов
Flyweight – Приспособленец
Чтобы
сэкономить память, создается один объект,
в который в разные моменты времени
загружаются разные данные
Бреслав А. А.
Паттерны проектирования.
Продолжение
Источники
Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес,
«Приемы объектно-ориентированного
проектирования. Паттерны проектирования»
М. Гранд, «Шаблоны проектирования в Java»
Bruce Eckel, «Thinking in Patterns with Java»
http://www.mindviewinc.com/
Бреслав А. А.
Паттерны проектирования.
Продолжение
Вопросы
Бреслав А. А.
Паттерны проектирования.
Продолжение