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/
Бреслав А. А.
Паттерны проектирования.
Продолжение
Вопросы
Бреслав А. А.
Паттерны проектирования.
Продолжение