Слайд 2www.itransition.com
Page
Содержание
Введение
GoF patterns
MVC & MVP
Antipatterns
![www.itransition.com Page Содержание Введение GoF patterns MVC & MVP Antipatterns](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-1.jpg)
Слайд 3www.itransition.com
Page
Зачем это надо?
Чтобы не решать каждую задачу с нуля
Использовать проверенные временем
![www.itransition.com Page Зачем это надо? Чтобы не решать каждую задачу с нуля](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-2.jpg)
решения
Заранее представлять последствия выбора того или иного варианта
Проектировать с учетом будущих изменений
Писать понятный и компактный код, который легко можно будет использовать повторно
Слайд 4www.itransition.com
Page
Что это такое?
Кристофер Александр: «Любой паттерн описывает задачу, которая снова и
![www.itransition.com Page Что это такое? Кристофер Александр: «Любой паттерн описывает задачу, которая](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-3.jpg)
снова возникает в нашей работе, а также принцип ее решения, причем таким образом, что это решение можно использовать миллион раз, ничего не изобретая заново»
Это не кусок кода, класс или dll
Это идея, метод решения, общий подход к целому классу задач, постоянно встречающихся на практике
Слайд 5www.itransition.com
Page
Описание паттерна
Имя (имена)
Задача (когда применять паттерн)
Решение
Результаты (следствия и компромиссы)
![www.itransition.com Page Описание паттерна Имя (имена) Задача (когда применять паттерн) Решение Результаты (следствия и компромиссы)](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-4.jpg)
Слайд 7www.itransition.com
Page
Null Value pattern
В некоторых ситуациях объект не может быть создан или
![www.itransition.com Page Null Value pattern В некоторых ситуациях объект не может быть](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-6.jpg)
не должен ничего делать.
Постоянные проверки сильно загромождают код и могут привести к ошибкам (Copy/Paste anti pattern)
Слайд 9www.itransition.com
Page
Результаты
Упрощение кода
Унификация вызовов
Уменьшение количества ошибок
![www.itransition.com Page Результаты Упрощение кода Унификация вызовов Уменьшение количества ошибок](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-8.jpg)
Слайд 10www.itransition.com
Page
GoF patterns
Порождающие паттерны
Структурные паттерны
Паттерны поведения
(Gang of Four: Erich Gamma, Richard Helm,
![www.itransition.com Page GoF patterns Порождающие паттерны Структурные паттерны Паттерны поведения (Gang of](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-9.jpg)
Ralph Johnson, John Vlissides)
Слайд 11www.itransition.com
Page
Порождающие паттерны
Обеспечивают независимость системы от процесса создания новых сущностей
Singleton
Abstract Factory
![www.itransition.com Page Порождающие паттерны Обеспечивают независимость системы от процесса создания новых сущностей Singleton Abstract Factory](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-10.jpg)
Слайд 12www.itransition.com
Page
Singleton
Гарантирует, что у класса есть только один экземпляр и предоставляет к
![www.itransition.com Page Singleton Гарантирует, что у класса есть только один экземпляр и](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-11.jpg)
нему глобальную точку доступа
Единственный экземпляр может расширяться путем порождения подклассов
Слайд 14www.itransition.com
Page
Пример кода
public class Singleton
{
private static readonly Singleton singleton = new Singleton();
private
![www.itransition.com Page Пример кода public class Singleton { private static readonly Singleton](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-13.jpg)
Singleton()
{
// Note private constructor
}
public static Singleton GetSingleton()
{
return singleton;
}
public void SomeFunction() { }
}
static void Main()
{
Singleton.GetSingleton().SomeFunction();
}
Слайд 15www.itransition.com
Page
Abstract Factory (Kit)
Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов,
![www.itransition.com Page Abstract Factory (Kit) Предоставляет интерфейс для создания семейств взаимосвязанных или](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-14.jpg)
не специфицируя конкретных классов
Позволяет легко перейти на использование другого семейства
Добавление новых объектов в семейство затруднено
Слайд 18www.itransition.com
Page
Пример
public class ToolFactory
{
private ToolFactory(){}
public static ToolFactory GetFactory()
{
//… - Singleton
}
public
![www.itransition.com Page Пример public class ToolFactory { private ToolFactory(){} public static ToolFactory](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-17.jpg)
ButtonTool CreateButtonTool(Tool tool, EventHandler toolClickHandler)
{
//Create Button Tool, add handler, set icon, caption, etc
}
public ButtonTool CreateStateButtonTool(Tool tool)
{
//Create Button Tool , caption, etc
}
}
Слайд 19www.itransition.com
Page
Паттерн Abstract Factory в действии
Public class SingleClickButtonTool : ButtonTool
{
private bool inHandler
![www.itransition.com Page Паттерн Abstract Factory в действии Public class SingleClickButtonTool : ButtonTool](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-18.jpg)
= false;
private EventHandler handler;
public SingleClickButtonTool (EventHandler handler)
OnButtonClick()
{
if (inHandler){return;}
inHandler = true;
try
{
handler.Invoke();
}
finally
{
inHandler = false;
}
}
}
Слайд 20www.itransition.com
Page
Структурные паттерны
Определяют, как классы и объекты группируются в более сложные структуры
Adapter
Facade
Proxy
Composite
![www.itransition.com Page Структурные паттерны Определяют, как классы и объекты группируются в более](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-19.jpg)
Слайд 21www.itransition.com
Page
Adapter (Wrapper)
Преобразует интерфейс одного класса к интерфейсу, ожидаемому клиентом
![www.itransition.com Page Adapter (Wrapper) Преобразует интерфейс одного класса к интерфейсу, ожидаемому клиентом](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-20.jpg)
Слайд 23Решение - множественное наследование
![Решение - множественное наследование](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-22.jpg)
Слайд 24Решение - использовать композицию объектов
![Решение - использовать композицию объектов](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-23.jpg)
Слайд 25www.itransition.com
Page
Пример кода
public class TextControlAdapter : BaseUserControl
{
TextControl innerControl; String rtfText;
public String RtfText
{
get
{
if
![www.itransition.com Page Пример кода public class TextControlAdapter : BaseUserControl { TextControl innerControl;](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-24.jpg)
(innerControl.Loaded) {return innerControl.Rtf;}
else {return rtfText;}
}
set
{
if (innerControl.Loaded) {innerControl.Rtf = value;}
else {rtfText = value;}
}
}
public TextControlAdapter()
{
innerControl = new TextControl();
}
}
Слайд 26www.itransition.com
Page
Facade
Определяет интерфейс более высокого уровня
Скрывает ненужные связи и зависимости
Упрощает использование подсистемы
![www.itransition.com Page Facade Определяет интерфейс более высокого уровня Скрывает ненужные связи и зависимости Упрощает использование подсистемы](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-25.jpg)
Слайд 28www.itransition.com
Page
Результат
Фасад переадресует запросы клиента классам системы, сами классы не «знают» о
![www.itransition.com Page Результат Фасад переадресует запросы клиента классам системы, сами классы не](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-27.jpg)
существовании фасада
Не нужно вникать во все тонкости и нюансы системы
Фасад не закрывает доступ к элементам системы, при необходимости можно использовать систему и в обход фасада
Слайд 29www.itransition.com
Page
Proxy (Surrogate)
Является суррогатом другого объекта и контролирует доступ к нему
«Создает тяжелые
![www.itransition.com Page Proxy (Surrogate) Является суррогатом другого объекта и контролирует доступ к](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-28.jpg)
объекты только по требованию»
Слайд 31www.itransition.com
Page
Пример кода
public class Graphic
{
public virtual void Draw(Point point)
{
//…
}
}
public class Image
![www.itransition.com Page Пример кода public class Graphic { public virtual void Draw(Point](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-30.jpg)
: Graphic
{
public Image(string fileName)
{
//Load image from file
}
public override void Draw(Point point){…}
}
Слайд 32www.itransition.com
Page
Использование прокси
public class ImageProxy : Graphic
{
private Image image;
private string fileName;
public void
![www.itransition.com Page Использование прокси public class ImageProxy : Graphic { private Image](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-31.jpg)
ImageProxy(string fileName)
{
this.fileName = fileName;
}
public void Draw(Point point)
{
if (image == null)
image = new Image(fileName);
image.Draw(point);
}
}
public class TextDocument
{
//…
this.Inset(new ImageProxy(“TestImage.png”));
}
Слайд 33www.itransition.com
Page
Composite
Компонует объекты в древовидные структуры
Позволяет единообразно трактовать индивидуальные и составные объекты
![www.itransition.com Page Composite Компонует объекты в древовидные структуры Позволяет единообразно трактовать индивидуальные и составные объекты](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-32.jpg)
Слайд 35www.itransition.com
Page
Пример кода
public class Equipment
{
private double netPrice; //Labor, $
public Equipment GetParent(){…}
public Equipment[]
![www.itransition.com Page Пример кода public class Equipment { private double netPrice; //Labor,](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-34.jpg)
GetParts(){…}
public void AddPart(Equipment part){…}
public void RemovePart(Equipment part){…}
public virtual double GetPrice()
{
double amount = netPrice;
foreach(Equipment part in GetParts())
{
amount += part.GetPrice();
}
}
//…
}
Слайд 36www.itransition.com
Page
Паттерны поведения
Инкапсулируют поведение и связи между объектами
Strategy
Template method
Mediator
![www.itransition.com Page Паттерны поведения Инкапсулируют поведение и связи между объектами Strategy Template method Mediator](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-35.jpg)
Слайд 37www.itransition.com
Page
Strategy (Policy)
Определяет семейство алгоритмов и делает их взаимозаменяемыми
Позволяет изменять алгоритмы независимо
![www.itransition.com Page Strategy (Policy) Определяет семейство алгоритмов и делает их взаимозаменяемыми Позволяет](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-36.jpg)
от клиентов, их использующих
Значительно упрощает добавление новых вариантов поведения
Слайд 39www.itransition.com
Page
Пример кода
public class CalculationStrategy
{
//…
public virtual double GetPrice(ArrayList priceItems){…}
}
public class RoundPriceStrategy :
![www.itransition.com Page Пример кода public class CalculationStrategy { //… public virtual double](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-38.jpg)
CalculationStrategy
{
int roundTo;
public RoundPriceStrategy Current(roundTo){… //Singleton}
public override double GetPrice(ArrayList priceItems){…}
}
public class LockPriceStrategy : CalculationStrategy
{
double totalAmount;
public LockPriceStrategy Current(totalAmount){… //Singleton}
public override double GetPrice(ArrayList priceItems){…}
}
Слайд 40www.itransition.com
Page
Использование стратегий
public class MainForm
{
//…
OnLockPriceChecked()
{
pricesTable.CalculationStrategy = LockPriceStrategy.Current(totalAmount);
}
OnRoundPriceChecked()
{
pricesTable.CalculationStrategy = RoundPriceStrategy.Current(roundTo);
}
}
![www.itransition.com Page Использование стратегий public class MainForm { //… OnLockPriceChecked() { pricesTable.CalculationStrategy](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-39.jpg)
Слайд 41www.itransition.com
Page
Template method
Определяет основу алгоритма
Позволяет подклассам переопределять отдельные шаги алгоритма, не меняя
![www.itransition.com Page Template method Определяет основу алгоритма Позволяет подклассам переопределять отдельные шаги](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-40.jpg)
структуры
Унифицирует поведение, позволяет легко изменять детали в каждом конкретном случае.
Слайд 43www.itransition.com
Page
Пример кода
public class BaseForm
{
public void CloseForm()
{
bool sureToClose = ConfirmClose();
if (!sureToClose) {return;}
bool
![www.itransition.com Page Пример кода public class BaseForm { public void CloseForm() {](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-42.jpg)
saved = Save();
if (saved) {this.Close();}
}
protected virtual bool ConfirmClose() {return true;}
protected virtual bool Save() {return true;}
}
Слайд 44www.itransition.com
Page
Продолжение примера
public class MainForm : BaseForm
{ //…
protected override Save()
{
bool saved = true;
if
![www.itransition.com Page Продолжение примера public class MainForm : BaseForm { //… protected](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-43.jpg)
(this.Modified && ShowSaveQuestion())
{
try{SaveData();}
catch(Exception exception)
{
ProcessException(exception); //e.g. show message
saved = false;
}
}
return saved;
}
}
Слайд 45www.itransition.com
Page
Mediator
Обеспечивает слабую связанность системы, избавляет объекты от необходимости явно ссылаться друг
![www.itransition.com Page Mediator Обеспечивает слабую связанность системы, избавляет объекты от необходимости явно](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-44.jpg)
на друга
Вместо многочисленных связей друг на друга все объескты системы хранят ссылку только на посредника
Слайд 48www.itransition.com
Page
Например
Взаимодействие модулей системы
Нет нужды разбираться в хитросплетениях системы.
Упрощен перенос методов между
![www.itransition.com Page Например Взаимодействие модулей системы Нет нужды разбираться в хитросплетениях системы.](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-47.jpg)
модулями
Возможность добавления/удаления модулей
Слайд 50www.itransition.com
Page
Результаты
Выносит взаимодействие между объектами в отдельный класс (легко изменять)
Преобразует связь много-ко-многим
![www.itransition.com Page Результаты Выносит взаимодействие между объектами в отдельный класс (легко изменять)](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-49.jpg)
в один-ко-многим (просто понять и поддерживать)
Слайд 51www.itransition.com
Page
MVC – Model-View-Controller
Отделяет вид от модели, устанавливая между ними протокол взаимодействий
Позволяет
![www.itransition.com Page MVC – Model-View-Controller Отделяет вид от модели, устанавливая между ними](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-50.jpg)
организовать различные представления одних и тех же данных
Слайд 54www.itransition.com
Page
MVP – Model-View-Presenter
Смысл – тот же, что и у MVC (отделить
![www.itransition.com Page MVP – Model-View-Presenter Смысл – тот же, что и у](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-53.jpg)
данные от представления)
Ориентируется на современные контролы, которые сами обрабатывают системные события
Основное отличие – View само ловит события и перенаправляет классу Presenter, который решает, что с этим делать (в MVC события ловит Controller)
Слайд 55www.itransition.com
Page
Пример кода
public class Presenter
{...
public Presenter(IView view, IModel model)
{
this.view = view;
this.model
![www.itransition.com Page Пример кода public class Presenter {... public Presenter(IView view, IModel](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-54.jpg)
= model;
SubscribeToViewEvents();
LoadViewFromModel();
}
}
Слайд 56www.itransition.com
Page
Результаты
Вынос поведения в отдельный класс – упрощает понимание кода
Позволяет вызывать события
![www.itransition.com Page Результаты Вынос поведения в отдельный класс – упрощает понимание кода](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-55.jpg)
и моделировать различные ситуации независимо от GUI – полезно как при тестировании, так и при изменеии представления
Слайд 57www.itransition.com
Page
Antipatterns
Описывают наиболее распространенные недостатки (что плохо и почему это плохо)
Как с
![www.itransition.com Page Antipatterns Описывают наиболее распространенные недостатки (что плохо и почему это](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-56.jpg)
этим бороться (refactoring)
Как выглядит приемлемое решение (когда стоит останавливаться)
Слайд 58www.itransition.com
Page
Patterns vs. AntiPatterns
![www.itransition.com Page Patterns vs. AntiPatterns](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-57.jpg)
Слайд 59www.itransition.com
Page
The Blob
Огромный класс, содержащий тучу методов, относящихся к логически разным объектам.
Невозможность
![www.itransition.com Page The Blob Огромный класс, содержащий тучу методов, относящихся к логически](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-58.jpg)
повторного использования
Модификация крайне затруднена, так как приходится следить за консистентностью большого количества данных
Да и вообще нарушает принципы ООП
Слайд 63www.itransition.com
Page
Poltergeist
Много мелких, перекрывающих друг друга классов
Классы имеют ограниченное использование
Большое количество связей
![www.itransition.com Page Poltergeist Много мелких, перекрывающих друг друга классов Классы имеют ограниченное](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-62.jpg)
– усложняет понимание и использование
Низкая производительность, неожиданные эффекты
Слайд 65www.itransition.com
Page
Исправление
Удалить ненужные, несущественные классы
Перегруппировать в более крупные связные классы
![www.itransition.com Page Исправление Удалить ненужные, несущественные классы Перегруппировать в более крупные связные классы](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-64.jpg)
Слайд 66www.itransition.com
Page
Lava Flow
Код, который никто не понимает
Недокументированный код
Код, который невозможно тестировать
Автор кода
![www.itransition.com Page Lava Flow Код, который никто не понимает Недокументированный код Код,](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-65.jpg)
давно отсутствует на проекте
Слайд 67www.itransition.com
Page
Как бороться
Не допускать (писать понятный, структурированный код и комментарии)
Не допускать (документировать
![www.itransition.com Page Как бороться Не допускать (писать понятный, структурированный код и комментарии)](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-66.jpg)
требования)
Стиснуть зубы, разобраться и рефакторить
Слайд 68www.itransition.com
Page
Golden Hammer
Использование одного и того же решения всюду, где только можно
![www.itransition.com Page Golden Hammer Использование одного и того же решения всюду, где](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-67.jpg)
и даже там, где нельзя
Игнорирование новых разработок
Решение:
Искать наиболее подходящие решения для данного конкретного случая
Слайд 69www.itransition.com
Page
Input Kludge
Возможность ввода данных, несоответствующих контексту
Возможность сохранения некорректных данных
Результат – «падения»
![www.itransition.com Page Input Kludge Возможность ввода данных, несоответствующих контексту Возможность сохранения некорректных](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-68.jpg)
и непредсказуемая работа
Решение:
Проверка всех входных данных на разных уровнях (DB, GUI)
Слайд 70www.itransition.com
Page
Refactoring
Это процесс систематического изменения программной системы, при котором внешнее поведение кода
![www.itransition.com Page Refactoring Это процесс систематического изменения программной системы, при котором внешнее](/_ipx/f_webp&q_80&fit_contain&s_1440x1080/imagesDir/jpg/374917/slide-69.jpg)
неизменно, но улучшается его внутренняя структура.
Это непрерывное приведение кода и комментариев в порядок.
Постоянный процесс, неотделимый от процесса разработки.
Мартин Фаулер «Рефакторинг».