Похожие презентации:
ПАКПС 2
1. Проектирование, Архитектура и Конструирование Программных систем
УНИВЕРСИТЕТ ДУБНАП.СЫЧЕВ
ЛЕКЦИЯ 2
2. Порождающие паттерны
Необходимость в порождающих паттернах в первую очередь связана с задачейослабления связей между составляющими сложной программной системы.
Если в реализации класса А необходимо использовать объекты класса В (т.е. либо в полях
класса А есть ссылка на объект класса В, либо объект класса В передается в метод класса А
как параметр), возникает зависимость между классами А и В. Т.е. при изменении класса В
необходимо проверить, что это не повлияло на работу класса А. А если надо заменить
класс В на более совершенный класс В2? Когда речь идет о сложной программной
системе, число классов которой исчисляется тысячами, проследить эти зависимости
исключительно трудно.
Стандартный способ борьбы с сильной связностью – разделить класс на функцию и
конструкцию. Термин функция здесь не из программирования, а из системной инженерии.
Функция – это то, что должен выполнять класс в рамках общей системы.
3. Интерфейс
В программировании функция класса задается ее интерфейсом, т.е. набором публичныхметодов и свойств, доступных извне.
В различных объектно-ориентированных языках программирования интерфейс класса
может задаваться по разному. В языках Java и C# есть специальная языковая конструкция
для интерфейсов.
4. Интерфейс
interface IStack <T>{
void push(T value);
T pop();
bool empty();
T top();
}
Для реализации данного интерфейса необходим класс, реализующий его.
5. Интерфейс
class Stack<T> : IStack<T>public bool empty()
{
{
List<T> values = new List<T>();
return values.Count == 0;
public void push(T value)
}
{
values.Add(value);
public T top()
}
{
public T pop()
return values[values.Count - 1];
{
}
T val = values[values.Count - 1];
values.RemoveAt(values.Count - 1);
return val;
}
}
6. Интерфейс
Если какому либо классу необходим стек, он будет использовать не класс Stack, аинтерфейс IStack, что существенно ослабляет зависимость.
class My
{
IStack<int> numbers;
// продолжение
}
Но возникает проблема – как инстанцировать эту ссылку? Экземпляр какого класса,
поддерживающего этот интерфейс, должен быть создан и в каком месте.
Для решения таких проблем и используются порождающие паттерны.
7. Factory method (Создатель)
Тип: порождающий.Синоним: Virtual Constructor.
Назначение: определяет интерфейс для создания объекта, оставляя подклассам решение
о том, какой класс инстанцировать.
Мотивация:
Рассмотрим пример с редактором векторной графики.
8. Factory method
Все фигуры, доступные в данном приложении являются объектами подклассов базовогокласса Figure, в нашем примере – Rectangle, Ellipse и Romb.
Здесь пользователь сначала выбирает тип порождаемой фигуры в инструментальном
меню, а потом по клику в рабочей области создается экземпляр соответствующего класса.
9. Factory method
Код метода panel_MouseDown будетсодержать что-то вроде этого, где selection
– поле, содержащее код выбранной
фигуры.
Figure f = null;
switch (selection)
{
Почему это плохо?
case 1:
f = new Rectangle();
Как добавить новую фигуру?
Многие современные программы
работают с плагинами – кодом,
добавляемым во время исполнения
программы. Как добавить новую фигуру
во время исполнения?
break;
case 2:
f = new Ellipse();
break;
}
10. Factory method
РешениеСоздать, параллельно с иерархией
классов Figure, иерархию классов
FigureCreator.
class FigureCreator
{
public virtual Figure CreateFigure()
{ return null; }
}
class RectangleCreator : FigureCreator
{
public override Figure CreateFigure()
{
return new Rectangle();
}
}
11. Factory method
Теперь код метода panel_MouseDown будетболее управляемый, где currCreator
соответствующий экземпляр класса
FigureCreator, инициируемый при нажатии на
кнопку выбора создаваемой фигуры.
Figure f = null;
Для добавления новой фигуры надо:
if (currCreator != null)
- написать класс, наследник Figure,
- написать класс, наследник FigureCreator,
- добавить новую кнопку на панель и код
инициализации этого «создателя» на эту
кнопку.
Все!!!
f = currCreator.CreateFigure();
12. Factory method
Структура:13. Factory method
Участники:Product – базовый класс для семейства конкретных продуктов, экземпляры которых
должны инстанцироваться;
Creator – базовый класс для семейства «создателей», классы реализующие метод,
создающий новый экземпляр соответствующего класса. Для каждого класса
ConcreteProduct должен быть соответствующий класс ConcreteCreator, задача которого
изготавливать экземпляры класса ConcreteProduct.
Реализация: в большинстве случаев не вызывает проблем.
14. Factory method
Результаты:(+) снижает зависимость между классами. В нашем примере редактор работает только с
экземплярами класса Figure, экземпляры конкретных классов создаются с помощью
«создателя».
15. Prototype (Прототип)
Тип: порождающий.Синоним: нет.
Назначение: создание нового объекта путем клонирования существующего прототипа.
Мотивация:
В качестве примера рассмотрим нотный редактор. В качестве рабочей области в нем будет
нотный стан, а в качестве инструментальной линейки – набор нот разной высоты и
длительности.
Основным объектом в такой программе будет нота – класс Note.
16. Prototype
Вопрос: как создавать новыеэкземпляры этого класса? Что
делать по клику в
инструментальной панели?
Решение: добавить в класс
Note метод Clone(), создающий
точную копию объекта. С
каждой кнопкой связать
экземпляр класса Note, копию
которого и вставлять в
программу.
17. Prototype
Второй пример – группировка различных фигур в векторном редакторе. Если высгруппировали интересную для вас композицию (точка, точка, два кружочка …), то как ее
поместить на инструментальную панель. Точнее – что делать при нажатии на эту кнопку и
как создать новый экземпляр этой группы?
Решение: как и в предыдущем случае добавим в базовом классе Figure метод Clone,
создающий копию объекта. Соответствующий кнопке «создатель» будет иметь копию
группы как прототип создаваемого объекта, и в методе CreateFigure – создавать и
возвращать копию своего прототипа.
18. Prototype
Структура:19. Prototype
Участники:Client – класс, использующий этот паттерн. В нашем случае, например, векторный
редактор. Он содержит ссылку на прототип, который может быть инстанцирован объектом
любого класса – наследника Prototype.
Prototype – базовый абстрактный класс для семейства классов, поддерживающих
операцию Clone(), метод позволяющий получить копию объекта.
ConcretePrototype1, ConcretePrototype2 – классы наследующие Prototype и реализующие
метод Clone.
20. Prototype
Реализация:1.
Основная проблема в реализации метода Clone – определить глубокое (deep) или
мелкое (shallow) копирование объекта.
Общий подход к реализации метода простой. Надо создать новый экземпляр и
скопировать туда значение полей объекта. Разница возникает, когда поле объекта
содержит ссылку на другой объект какого-то класса. Если дубликат получает копию ссылки,
то это мелкое копирование. Если ссылаемый объект, в свою очередь, дублируется и
дубликат получает ссылку на копию объекта, то это глубокое копирование.
Никакого правильного ответа на этот вопрос нет. В различных случаях надо использовать
разное решение.
21. Prototype
2.Второй вопрос – как управлять множеством прототипов.
Для этого логично завести менеджер прототипов – коллекцию прототипов, каждый объект в
котором идентифицируется своим ключом. Client запрашивает нужный ему прототип по
ключу перед клонированием.
22. Prototype
Результаты:(+) ослабление связности
(+) возможно добавление и удаление прототипов во время выполнения
(+) спецификация новых прототипов путем изменения значений
(+) динамическое конфигурирование приложения набором прототипов
Программирование