design patterns part 2
TRANSCRIPT
![Page 1: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/1.jpg)
Шаблони проектування
Частина 2
![Page 2: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/2.jpg)
Розглянемо
• Presentation pattern Model View Presenter
• Шаблони поведінки• Структурні шаблони• Деякі вже відомі нам шаблони
![Page 3: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/3.jpg)
Model View Presenter
![Page 4: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/4.jpg)
Призначення
Розділення • Даних для показу• Логіки програми• Відображення даних
![Page 5: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/5.jpg)
View Model
Presenter
updates
fetches
change
request
displays
Сповіщає Presenter про
дії користувача,відображає
дані
Завантажує дані, передає дані на View, реагує на дії
користувача
Дані для показу
![Page 6: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/6.jpg)
View Model
PresenterUI
DomainData
Access
![Page 7: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/7.jpg)
Відповідальності: Model
• Контейнер для даних для відображення• Supervising Controller: View знає про
Модель• Passive View: View не знає про Модель• Також може бути класом з предметної
області
![Page 8: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/8.jpg)
Відповідальності: View
• Є формою, показує UI• Створює Презентер, передає себе йому• Перенаправляє дії користувача
Презентеру• Може знати про Модель• Або може надавати детальний
інтерфейс для встановлення даних• Звертається до конкретного
Презентера
![Page 9: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/9.jpg)
Відповідальності: Presenter
• Реагує на дії користувача• Оновлює View даними з Моделі• Позбавляє View відповідальності за
логіку та взаємодію з бізнес-класами та data access– Презентер отримує дані з бізнес-рівня– Трансформація/фільтрування даних– Презентер зберігає зміни, зроблені
користувачем
• Звертається до View через інтерфейс IView
![Page 10: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/10.jpg)
Модифікації
• Supervising Controller– View відповідає за data binding Моделі– Презентер передає Модель на View– Презентер керує складнішими
взаємодіями
• Passive View– Презентер відповідає за передачу
кожної частини даних на View– View лише відображає передані
прості дані
![Page 11: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/11.jpg)
Застосовується
• Windows Forms– Існують розвинені MVP фреймворки
• ASP.NET Web Forms
![Page 12: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/12.jpg)
Strategy
![Page 13: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/13.jpg)
public sealed class SurveysImporter { public void Import() { // ... initialize import here switch (GetFileStorageType(importContext)) { case SurveysStorageType.Xls: ImportFromExcel(); break; case SurveysStorageType.Csv: ImportFromCsvFile(); break; case ... default: DoNothingButLog(); break; } // ... report import completed successfully }
![Page 14: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/14.jpg)
public sealed class SurveysImporterWithStrategy{ private readonly IFileImporterStrategy fileImporterStrategy; public void Import() { // ... initialize import here fileImporterStrategy.Import(); // ... report import completed successfully }
![Page 15: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/15.jpg)
Призначення
• Інкапсуляція алгоритму• Зміна та розвиток алгоритму
окремо від клієнта• Винесення наборів різної
поведінки з класу• Усунення умовних операторів• Уникнення зміни класу при
додаванні нового алгоритму
![Page 16: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/16.jpg)
Реалізація
• Створення класу-стратегії для кожної варіації алгоритму
• Створення спільного інтерфейсу для всіх цих алгоритмів
• Стратегія може використовувати клас-клієнт
• Або інший контекст
![Page 17: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/17.jpg)
public class FilesSender{ public void SendToServer(Directory directory, Context context) { if (context.SendTopLevelFilesFirst) { foreach (var file in directory.Files) { SendToServer(file); } foreach (var childDirectory in directory.Directories) { SendToServer(childDirectory, context); } }
![Page 18: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/18.jpg)
Higher order functions
• Є стратегіями
![Page 19: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/19.jpg)
public class FilesSender{ private readonly Func<Directory, IEnumerable<File>> enumerateFiles;
public FilesSenderWithStrategy( Func<Directory, IEnumerable<File>> directoryTraverser) { enumerateFiles = directoryTraverser; }
public void SendToServer(Directory directory, Context context) {
foreach (var file in enumerateFiles(directory)) { SendToServer(file); } }
![Page 20: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/20.jpg)
Template Method
![Page 21: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/21.jpg)
public class SurveysImporter{ public void Import() { InitializeImport(); DoImport(); NotifyUsers(); ReportSuccessfullCompletion(); }
![Page 22: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/22.jpg)
public class CsvSurveysImporter : SurveysImporterWithTemplateMethod{ protected override void DoImport() { // CSV import implementation here }
protected override void NotifyUsers() { // users notification implementation here }}
![Page 23: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/23.jpg)
Призначення• Алгоритм складається з декількох
кроків• Реалізація одного кроку може
змінюватись• (або декількох кроків)• Інкапсуляція незмінної послідовності
кроків• Можливість задати реалізацію кроків,
що можуть змінюватись• Зміна кроків алгоритму без зміни його
структури
![Page 24: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/24.jpg)
Реалізація
• Підкласи перевизначають окремі кроки алгоритму, визначеного в базовому класі
• Базується на наслідуванні• Альтернатива – Strategy
![Page 25: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/25.jpg)
Приклад
• ASP.NET page lifecycle– OnInit(), OnLoad() etc.
![Page 26: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/26.jpg)
Command
![Page 27: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/27.jpg)
private void Import(Survey survey){ if (survey.CreatedBy == currentUser && survey.CreatedOn < DateTime.Today && ( new[] { SurveyState.New, SurveyState.Finished } .Contains(survey.State) || survey.State == SurveyState.Paused && !survey.HasAnswers ) && !AlreadyExistsSurveyWithTitle(survey.Title)) { // create new or update existing survey }}
![Page 28: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/28.jpg)
Призначення
• Представлення дії як об’єкта• Відділення виконання дії від
деталей і залежностей, необхідних для реалізації дії
• Додавання нових дій без зміни клієнтів
![Page 29: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/29.jpg)
public interface ICommand{ void Execute();} Не приймає
аргументів
public interface ICommand<T>{ void ExecuteFor(T obj);}
![Page 30: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/30.jpg)
public class ImportSurveyCommand : ICommand<Survey>{ private readonly string currentUser; private readonly object importContext;
public ImportSurveyCommand(string currentUser, object importContext) { this.currentUser = currentUser; this.importContext = importContext; }
public void ExecuteFor(Survey obj) { // create new or update existing survey }}
![Page 31: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/31.jpg)
private void Import(Survey survey){ if (survey.CreatedBy == currentUser && ...) { var importSurvey = new ImportSurveyCommand( currentUser, GetImportContext()); importSurvey.ExecuteFor(survey); }}
![Page 32: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/32.jpg)
public interface ICommand{ bool CanExecute(); void Execute(); void Undo();}
Команда може використовуватись для undo
функціональності
![Page 33: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/33.jpg)
Specification
![Page 34: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/34.jpg)
private void Import(Survey survey){ if (survey.CreatedBy == currentUser && survey.CreatedOn < DateTime.Today && ( new[] { SurveyState.New, SurveyState.Finished } .Contains(survey.State) || survey.State == SurveyState.Paused && !survey.HasAnswers ) && !AlreadyExistsSurveyWithTitle(survey.Title)) { // create new or update existing survey }}
![Page 35: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/35.jpg)
Передумови
• Бізнес-правило містить багато коду• Правило логічно складне• Правило може часто змінюватись• Правил може бути декілька
• Призначення: спрощення коду класу-клієнта
![Page 36: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/36.jpg)
public interface ISpecification<T>{ bool IsSatisfiedBy(T obj);}
public class SurveyShouldBeImported : ISpecification<Survey>{ public bool IsSatisfiedBy(Survey obj) { // ... }}
![Page 37: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/37.jpg)
Реалізація
• Інкапсулює булеве бізнес-правило• Можливі композитні Специфікації– AndSpecification, OrSpecification,
NotSpecification
• Можливе поєднання Команд та Специфікацій
![Page 38: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/38.jpg)
public class AndSpecification<T> : ISpecification<T>{ private readonly ISpecification<T> first; private readonly ISpecification<T> second;
public AndSpecification(ISpecification<T> first, ISpecification<T> second) { this.first = first; this.second = second; }
public bool IsSatisfiedBy(T obj) { return first.IsSatisfiedBy(obj) && second.IsSatisfiedBy(obj); }}
![Page 39: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/39.jpg)
Adapter
![Page 40: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/40.jpg)
Призначення
• Класи-клієнти використовують певний інтерфейс
• Потрібне перетворення інтерфейсу одного класу в інтерфейс іншого
• Для використання існуючих класів • Адаптує один інтерфейс до іншого
![Page 41: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/41.jpg)
Прикладpublic interface ISurveyRepository{ IList<Survey> GetAll(); Survey Get(int id);}
![Page 42: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/42.jpg)
Decorator
![Page 43: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/43.jpg)
Призначення
• Зміна поведінки об’єкта без зміни інтерфейсу
• Додання функціональності динамічно
• Приклад: Додавання валідації
![Page 44: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/44.jpg)
public interface ISurveysImporter{ void Import();}
public sealed class SurveysImporter : ISurveysImporter{ ... public void Import() { // ... initialize import here fileImporterStrategy.Import(); // ... report completed successfully }}
![Page 45: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/45.jpg)
public sealed class SecurityCheckingSurveysImporter : ISurveysImporter { private readonly ISurveysImporter importer;
public void Import() { if (GetCurrentUserRole() != "Admin") { throw new InvalidOperationException( "User is not allowed to import surveys."); } importer.Import(); }...
![Page 46: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/46.jpg)
Реалізація• Декоратор реалізує інтерфейс
початкового об’єкту• Декоратор зберігає посилання на
початковий об’єкт• Початковий об’єкт не знає про
додаткову функціональність• Декоратори можуть поєднуватись• Композиція замість наслідування
![Page 47: Design patterns part 2](https://reader035.vdocuments.net/reader035/viewer/2022062300/559281bc1a28ab50678b4636/html5/thumbnails/47.jpg)
Вже відомі шаблони• Iterator– IEnumerable<T> + IEnumerator<T>– yield return -- компілятор сам генерує
ітератор
• Observer– C# events, based on delegates
• Proxy– Доступ до веб-сервісів
• MVC• Repository