5. Сповіщає Presenter displays
про дії
користувача,
відображає дані
Дані для показу
updates
View Model
change
request Presenter fetches
Завантажує дані, передає дані на
View, реагує на дії користувача
7. Відповідальності: Model
• Контейнер для даних для відображення
• Supervising Controller: View знає про Модель
• Passive View: View не знає про Модель
• Також може бути класом з предметної області
8. Відповідальності: View
• Є формою, показує UI
• Створює Презентер, передає себе йому
• Перенаправляє дії користувача Презентеру
• Може знати про Модель
• Або може надавати детальний інтерфейс для
встановлення даних
• Звертається до конкретного Презентера
9. Відповідальності: Presenter
• Реагує на дії користувача
• Оновлює View даними з Моделі
• Позбавляє View відповідальності за логіку та
взаємодію з бізнес-класами та data access
– Презентер отримує дані з бізнес-рівня
– Трансформація/фільтрування даних
– Презентер зберігає зміни, зроблені користувачем
• Звертається до View через інтерфейс IView
10. Модифікації
• Supervising Controller
– View відповідає за data binding Моделі
– Презентер передає Модель на View
– Презентер керує складнішими взаємодіями
• Passive View
– Презентер відповідає за передачу кожної
частини даних на View
– View лише відображає передані прості дані
13. 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
}
14. public sealed class SurveysImporterWithStrategy
{
private readonly IFileImporterStrategy
fileImporterStrategy;
public void Import()
{
// ... initialize import here
fileImporterStrategy.Import();
// ... report import completed successfully
}
15. Призначення
• Інкапсуляція алгоритму
• Зміна та розвиток алгоритму окремо від
клієнта
• Винесення наборів різної поведінки з класу
• Усунення умовних операторів
• Уникнення зміни класу при додаванні
нового алгоритму
16. Реалізація
• Створення класу-стратегії для кожної
варіації алгоритму
• Створення спільного інтерфейсу для всіх
цих алгоритмів
• Стратегія може використовувати клас-
клієнт
• Або інший контекст
17. 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);
}
}
21. public class SurveysImporter
{
public void Import()
{
InitializeImport();
DoImport();
NotifyUsers();
ReportSuccessfullCompletion();
}
22. public class CsvSurveysImporter :
SurveysImporterWithTemplateMethod
{
protected override void DoImport()
{
// CSV import implementation here
}
protected override void NotifyUsers()
{
// users notification implementation here
}
}
23. Призначення
• Алгоритм складається з декількох кроків
• Реалізація одного кроку може змінюватись
• (або декількох кроків)
• Інкапсуляція незмінної послідовності кроків
• Можливість задати реалізацію кроків, що можуть
змінюватись
• Зміна кроків алгоритму без зміни його структури
28. Призначення
• Представлення дії як об’єкта
• Відділення виконання дії від деталей і
залежностей, необхідних для реалізації дії
• Додавання нових дій без зміни клієнтів
29. public interface ICommand
{
void Execute();
} Не приймає
аргументів
public interface ICommand<T>
{
void ExecuteFor(T obj);
}
30. 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
}
}
31. private void Import(Survey survey)
{
if (survey.CreatedBy == currentUser &&
...)
{
var importSurvey = new ImportSurveyCommand(
currentUser,
GetImportContext());
importSurvey.ExecuteFor(survey);
}
}
32. Команда може використовуватись для
undo функціональності
public interface ICommand
{
bool CanExecute();
void Execute();
void Undo();
}
35. Передумови
• Бізнес-правило містить багато коду
• Правило логічно складне
• Правило може часто змінюватись
• Правил може бути декілька
• Призначення: спрощення коду класу-клієнта
36. public interface ISpecification<T>
{
bool IsSatisfiedBy(T obj);
}
public class SurveyShouldBeImported :
ISpecification<Survey>
{
public bool IsSatisfiedBy(Survey obj)
{
// ...
}
}
37. Реалізація
• Інкапсулює булеве бізнес-правило
• Можливі композитні Специфікації
– AndSpecification, OrSpecification,
NotSpecification
• Можливе поєднання Команд та
Специфікацій
38. 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);
}
}
40. Призначення
• Класи-клієнти використовують певний
інтерфейс
• Потрібне перетворення інтерфейсу одного
класу в інтерфейс іншого
• Для використання існуючих класів
• Адаптує один інтерфейс до іншого
43. Призначення
• Зміна поведінки об’єкта без зміни
інтерфейсу
• Додання функціональності динамічно
• Приклад: Додавання валідації
44. public interface ISurveysImporter
{
void Import();
}
public sealed class SurveysImporter :
ISurveysImporter
{
...
public void Import()
{
// ... initialize import here
fileImporterStrategy.Import();
// ... report completed successfully
}
}
45. 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();
}
...
46. Реалізація
• Декоратор реалізує інтерфейс початкового
об’єкту
• Декоратор зберігає посилання на
початковий об’єкт
• Початковий об’єкт не знає про додаткову
функціональність
• Декоратори можуть поєднуватись
• Композиція замість наслідування
47. Вже відомі шаблони
• Iterator
– IEnumerable<T> + IEnumerator<T>
– yield return -- компілятор сам генерує ітератор
• Observer
– C# events, based on delegates
• Proxy
– Доступ до веб-сервісів
• MVC
• Repository