design patterns part 2

47
Шаблони проектування Частина 2

Upload: victor-matyushevskyy

Post on 30-Jun-2015

1.885 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Design patterns part 2

Шаблони проектування

Частина 2

Page 2: Design patterns part 2

Розглянемо

• Presentation pattern Model View Presenter

• Шаблони поведінки• Структурні шаблони• Деякі вже відомі нам шаблони

Page 3: Design patterns part 2

Model View Presenter

Page 4: Design patterns part 2

Призначення

Розділення • Даних для показу• Логіки програми• Відображення даних

Page 5: Design patterns part 2

View Model

Presenter

updates

fetches

change

request

displays

Сповіщає Presenter про

дії користувача,відображає

дані

Завантажує дані, передає дані на View, реагує на дії

користувача

Дані для показу

Page 6: Design patterns part 2

View Model

PresenterUI

DomainData

Access

Page 7: Design patterns part 2

Відповідальності: Model

• Контейнер для даних для відображення• Supervising Controller: View знає про

Модель• Passive View: View не знає про Модель• Також може бути класом з предметної

області

Page 8: Design patterns part 2

Відповідальності: View

• Є формою, показує UI• Створює Презентер, передає себе йому• Перенаправляє дії користувача

Презентеру• Може знати про Модель• Або може надавати детальний

інтерфейс для встановлення даних• Звертається до конкретного

Презентера

Page 9: Design patterns part 2

Відповідальності: Presenter

• Реагує на дії користувача• Оновлює View даними з Моделі• Позбавляє View відповідальності за

логіку та взаємодію з бізнес-класами та data access– Презентер отримує дані з бізнес-рівня– Трансформація/фільтрування даних– Презентер зберігає зміни, зроблені

користувачем

• Звертається до View через інтерфейс IView

Page 10: Design patterns part 2

Модифікації

• Supervising Controller– View відповідає за data binding Моделі– Презентер передає Модель на View– Презентер керує складнішими

взаємодіями

• Passive View– Презентер відповідає за передачу

кожної частини даних на View– View лише відображає передані

прості дані

Page 11: Design patterns part 2

Застосовується

• Windows Forms– Існують розвинені MVP фреймворки

• ASP.NET Web Forms

Page 12: Design patterns part 2

Strategy

Page 13: Design patterns part 2

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

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

Призначення

• Інкапсуляція алгоритму• Зміна та розвиток алгоритму

окремо від клієнта• Винесення наборів різної

поведінки з класу• Усунення умовних операторів• Уникнення зміни класу при

додаванні нового алгоритму

Page 16: Design patterns part 2

Реалізація

• Створення класу-стратегії для кожної варіації алгоритму

• Створення спільного інтерфейсу для всіх цих алгоритмів

• Стратегія може використовувати клас-клієнт

• Або інший контекст

Page 17: Design patterns part 2

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

Higher order functions

• Є стратегіями

Page 19: Design patterns part 2

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

Template Method

Page 21: Design patterns part 2

public class SurveysImporter{ public void Import() { InitializeImport(); DoImport(); NotifyUsers(); ReportSuccessfullCompletion(); }

Page 22: Design patterns part 2

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

Призначення• Алгоритм складається з декількох

кроків• Реалізація одного кроку може

змінюватись• (або декількох кроків)• Інкапсуляція незмінної послідовності

кроків• Можливість задати реалізацію кроків,

що можуть змінюватись• Зміна кроків алгоритму без зміни його

структури

Page 24: Design patterns part 2

Реалізація

• Підкласи перевизначають окремі кроки алгоритму, визначеного в базовому класі

• Базується на наслідуванні• Альтернатива – Strategy

Page 25: Design patterns part 2

Приклад

• ASP.NET page lifecycle– OnInit(), OnLoad() etc.

Page 26: Design patterns part 2

Command

Page 27: Design patterns part 2

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

Призначення

• Представлення дії як об’єкта• Відділення виконання дії від

деталей і залежностей, необхідних для реалізації дії

• Додавання нових дій без зміни клієнтів

Page 29: Design patterns part 2

public interface ICommand{ void Execute();} Не приймає

аргументів

public interface ICommand<T>{ void ExecuteFor(T obj);}

Page 30: Design patterns part 2

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

private void Import(Survey survey){ if (survey.CreatedBy == currentUser && ...) {     var importSurvey = new ImportSurveyCommand( currentUser,  GetImportContext());     importSurvey.ExecuteFor(survey); }}

Page 32: Design patterns part 2

public interface ICommand{    bool CanExecute();    void Execute();    void Undo();}

Команда може використовуватись для undo

функціональності

Page 33: Design patterns part 2

Specification

Page 34: Design patterns part 2

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

Передумови

• Бізнес-правило містить багато коду• Правило логічно складне• Правило може часто змінюватись• Правил може бути декілька

• Призначення: спрощення коду класу-клієнта

Page 36: Design patterns part 2

public interface ISpecification<T>{    bool IsSatisfiedBy(T obj);}

public class SurveyShouldBeImported :  ISpecification<Survey>{    public bool IsSatisfiedBy(Survey obj)    {        // ...    }}

Page 37: Design patterns part 2

Реалізація

• Інкапсулює булеве бізнес-правило• Можливі композитні Специфікації– AndSpecification, OrSpecification,

NotSpecification

• Можливе поєднання Команд та Специфікацій

Page 38: Design patterns part 2

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

Adapter

Page 40: Design patterns part 2

Призначення

• Класи-клієнти використовують певний інтерфейс

• Потрібне перетворення інтерфейсу одного класу в інтерфейс іншого

• Для використання існуючих класів • Адаптує один інтерфейс до іншого

Page 41: Design patterns part 2

Прикладpublic interface ISurveyRepository{ IList<Survey> GetAll(); Survey Get(int id);}

Page 42: Design patterns part 2

Decorator

Page 43: Design patterns part 2

Призначення

• Зміна поведінки об’єкта без зміни інтерфейсу

• Додання функціональності динамічно

• Приклад: Додавання валідації

Page 44: Design patterns part 2

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

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

Реалізація• Декоратор реалізує інтерфейс

початкового об’єкту• Декоратор зберігає посилання на

початковий об’єкт• Початковий об’єкт не знає про

додаткову функціональність• Декоратори можуть поєднуватись• Композиція замість наслідування

Page 47: Design patterns part 2

Вже відомі шаблони• Iterator– IEnumerable<T> + IEnumerator<T>– yield return -- компілятор сам генерує

ітератор

• Observer– C# events, based on delegates

• Proxy– Доступ до веб-сервісів

• MVC• Repository