Перейти до вмісту

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);
	}
}

Див. також

[ред. | ред. код]

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

[ред. | ред. код]