Model-View-Presenter

Діаграма взаємодії між компонентами шаблону MVP

Модель–Представлення–Пред'явник (англ. Model-View-Presenter, MVP) — шаблон проектування, похідний від MVC, що відділяє візуальне відображення та поведінку обробки подій у різні класи, а саме: Представлення (View) та Пред'явник (Presenter).

Передумови для застосування

  • Виникає необхідність відділити бізнес-логіку від логіки інтерфейсу користувача, щоб зробити його простішим для розуміння та підтримки.
  • Стоїть задача надати доступ до коду різним сторінкам, що потребують однакової поведінки.
  • Потрібно максимізувати обсяг коду, що підлягає автоматизованому тестуванню.

Складові частини

Модель

Модель являє собою клас для визначення даних, які будуть відображатися або над якими будуть проводитися інші дії у інтерфейсі користувача.

Представлення

Клас Представлення управляє елементами на сторінці, та направляє події до класу Пред'явника.

Презентер

Пред'явник містить логіку реагування на події, оновлює Модель (бізнес-логіки і даних з програми) і, в свою чергу, маніпулює станом Представлення. Для полегшення тестування Пред'явника, він повинен мати посилання на інтерфейс Представлення замість посилання на конкретну реалізацію. Як наслідок, ви можете легко замінити діюче Представлення на макет для виконання тестів.

Різновиди

Passive View

Passive View

Представлення майже не містить логіки. Пред'явник — посередник між Представленням та Моделлю. Крім того, у Представлення та Моделі повністю закритий доступ один до одного. Модель може викликати події , але Пред'явник підписується на них для оновлення Представлення.

У "Пасивному Представленні" немає прямої прив'язки даних, натомість, Представлення надає set-властивості , які Пред'явник використовує для надання значень даним. Всі стани керуються Пред'явником, а не Представленням.

Плюси: легкість тестування, прозорий поділ Представлення та Моделі.

Мінуси: витрати часу на самостійну прив'язку даних.

Supervising Controller

Supervising Controller

У цьому випадку, Пред'явник обробляє події користувача. Представлення зв'язується з Моделлю безпосередньо через прив'язку даних. У цьому випадку, завдання Пред'явника "пройти" від Моделі до Представлення, таким чином, щоб могла відбутися прив'язка даних. Пред'явник буде також містити логіку для таких подій як натискання клавіш, навігації тощо.

Плюси: зменшення обсягу коду, за рахунок використання прив'язки даних.

Мінуси: більш складне тестування, зменшення енкапсуляції у Представленні через прямий зв'язок з Моделлю.


Реалізація

Приклад реалізації шаблону у Windows Forms.

Оголосимо модель, що містить логіку аплікації, не залежну від представлення.

public class OrderDto
{
	public string Name { get; set; }
}

public interface IOrdersModel
{
	OrderDto[] LoadOrders();
}

public class OrdersModel : IOrdersModel
{
	public OrderDto[] LoadOrders()
	{
		return new OrderDto[]
		{
			new OrderDto(){ Name = "Item1" },
			new OrderDto(){ Name = "Item2" },
		};
	}
}

Додамо інтерфейс взаємодії із виглядом та його реалізацію.

// інтерфейс взаємодії не залежить від технологій
public interface IOrdersView
{
	void Display(OrderDto[] orders);
}

// реалізація інтерфейсу взаємодії прив'язана до середовища розгортання
public partial class OrdersForm : Form, IOrdersView
{
	private OrdersPresenter presenter;

	public OrdersForm()
	{
		InitializeComponent();
		presenter = new OrdersPresenter(this, new OrdersModel());
	}

	// виклик презентера із вигляду
	private void LoadOrdersButton_Click(object sender, EventArgs e)
	{
		presenter.LoadOrders();
	}

	// зміна стану представлення
	void IOrdersView.Display(OrderDto[] orders)
	{
		var orderNames = orders.Select(x => x.Name).ToArray();

		this.orderListBox.Items.AddRange(orderNames);
	}
}

Та додамо презентер — компонент, що зв'язує логіку аплікації (модель) із виглядом.

public class OrdersPresenter
{
	private readonly IOrdersView view;
	private readonly IOrdersModel model;

	public OrdersPresenter(IOrdersView view, IOrdersModel model)
	{
		this.view = view;
		this.model = model;
	}

	// метод-обробник, виконується при взаємодії користувача із виглядом
	public void LoadOrders()
	{
		// керування моделю
		var orders = model.LoadOrders();

		// маніпуляція представленням
		view.Display(orders);
	}
}

Див. також

Джерела та література

  • Martin Fowler. Supervising Controller [Архівовано 2 лютого 2014 у Wayback Machine.]
  • patterns & practices Web Client Developer Guidance [Архівовано 3 лютого 2014 у Wayback Machine.]
  • What are MVP and MVC? [Архівовано 21 січня 2014 у Wayback Machine.]
  • п
  • о
  • р
Основні шаблони
Абстрагування (програмування) • Делегування (Delegation) • Інтерфейс (Interface) • Інтерфейс-маркер (Marker Interface) • Незмінний інтерфейс (Immutable Interface) • Незмінний об'єкт (Immutable Object) • Функціональний дизайн (Functional Design) • Контейнер властивостей (Property Container) • Канал подій (Event Channel)
Твірні шаблони
Абстрактна фабрика (Abstract Factory) • Будівник (Builder) • Одинак (Singleton) • Прототип (Prototype) • Фабричний метод (Factory Method) • Пул об'єктів • Fluent builder • Мультитон • Лінива ініціалізація Отримання ресурсу, як ініціалізація (Resource Acquisition Is Initialization)
Структурні шаблони
Адаптер (Adapter) • Декоратор (Decorator) • Замісник (Proxy) • Компонувальник (Composite) • Міст (Bridge) • Легковаговик (Flyweight) • Фасад (Facade) • Модуль • Виділення приватного класу даних • Близнюки
Шаблони поведінки
Відвідувач (Visitor) • Інтерпретатор (Interpreter) • Ітератор (Iterator) • Команда (Command) • Ланцюжок відповідальностей (Chain of Responsibility) • Посередник (Mediator) • Спостерігач (Observer) • Стан (State) • Стратегія (Strategy) • Знімок (Memento) • Шаблонний метод (Template Method) • Одноразовий відвідувач • Null object • Специфікація • Feature toggle • Мультиметод • Перехоплювач (Interceptor) • Накопичувач (Collecting Parameter) • Слуга (Servant)
Функційні
Функтор • Генератор • Замикання • Монади • Каррінг • Функція зворотного виклику • Функція вищого порядкуВкладена функція • Результат (Result)
Патерни
конкурентного
програмування
Блокування • Модель акторів • Бар'єр • Монітор • Семафор • М'ютексПланувальник операційної системиЛокальна пам'ять ниток • Оптимістичне блокування (Optimistic Offline Lock) • Песимістичне блокування (Pessimistic Offline Lock) • Активний об'єкт (Active Object)
Кешування
Архітектурні
Базові шаблони
Клієнт-серверна архітектураFront end та back endТриярусна архітектура • Гексагональна архітектура (Архітектура портів та адаптерів) • Відокремлений інтерфейс (Separated Interface) • Сервісно-орієнтована архітектураМікросервісиPush/Pull модель
Шаблони об'єктного структурування
Шаблони представлення
MVCPureMVCHMVC • MVP • MVVMPost/Redirect/Get
Шаблони предметно-орієнтованого проєктування
Rich/Anemic модельDDD • Інваріант • EntityValue ObjectAggregate RootDTORepositoryПатерн сервісного рівня (Service Layer) • Фабричний метод (Factory Method) • Специфікація
Шаблони сервісно-орієнтованої архітектури
Архітектура
корпоративних
програмних
додатків
Базові шаблони
Об'єкт-значення (Value Object) • Гроші (Money) • Особливий випадок (Special Case) • Супертип рівня (Layer Supertype) • Відокремлений інтерфейс (Separated Interface) • Шлюз (Gateway) • Розподільник (Mapper) • Реєстр (Registry) • Плагін (Plugin) • Набір записів (Record Set) • Заглушка сервісу (Service Stub)
Шаблони логіки домену
Сценарій транзакції (Transaction script) • Модель предметної області (Domain model) • Обробник таблиці (Table Module) • Патерн сервісного рівня (Service Layer)
Шаблони сховища даних
Активний запис (Active Record) • Шлюз до даних таблиці (Table Data Gateway) • Шлюз до даних запису (Row Data Gateway) • Відображення даних (Data Mapper)
Шаблони об'єктно-реляційної поведінки
Одиниця роботи (Unit Of Work) • Мапа відповідності (Identity Map) • Ліниве завантажування (Lazy Load)
Шаблони об'єктно-реляційного структурування
Поле первинного ключа (Identity Field) • Розмітка зовнішніх ключів (Foreign Key Mapping) • Розмітка зв'язків таблиць (Association Table Mapping) • Відображення залежних об'єктів (Dependent Mapping) • Об'єднане значення (Embedded Value) • Серіалізований великий об'єкт (Serialized LOB) • Наслідування з однією таблицею (Single Table Inheritance) • Наслідування з таблицею для кожного класу (Class Table Inheritance) • Наслідування з таблицею для кожного конкретного класу (Concrete Table Inheritance) • Відображення із наслідуванням (Inheritance Mappers) • База даних звітності
Шаблони обробки об'єктно-реляційних метаданих
Відображення на основі метаданих (Metadata Mapping) • Об'єкт-запит (Query Object) • Сховище (Repository)
Шаблони вебпредставлення
Модель-вид-контролер (Model View Controller) • Контролер сторінки (Page Controller) • Єдина точка входу (Front controller) • Контролер аплікації (Application Controller) • Шаблонізатор (Template View) • Перетворювач (Transform View) • Двокрокова шаблонізація (Two Step View)
Шаблони розподіленої обробки даних
Шаблони локального конкурентного програмування
Оптимістичне блокування (Optimistic Offline Lock) • Песимістичне блокування (Pessimistic Offline Lock) • Блокування із низьким рівнем деталізації (Coarse Grained Lock) • Неявне блокування (Implicit Lock)
Шаблони збереження стану сеансу
Збереження стану сеансу на стороні клієнта (Client Session State) • Збереження стану сеансу на стороні сервера (Server Session State) • Збереження стану сеансу в базі даних (Database Session State)
Тестування
PageObjectМакет об'єкта (Mock Object) • Заглушка сервісу (Service Stub) • Скромний об'єкт (Humble Object)
Інші
Впровадження залежностейIoC контейнер • Локатор служб (Service Locator) • М'яке видалення (Soft Delete) • Auditable Entity • Entity Component System (ECS)Extract, Transform, Load (ETL)
Див. також
Design Patterns (книга) • Бізнес-логіка • Інваріант • Зв'язність (Coupling) • Пов'язаність (Cohesion) • Закон ДеметриKISSDRYYAGNITell Don't Ask • SOLID • CQRSGRASPІдемпотентністьМартін ФаулерАнтипатерн