Model-View-Presenter
Model View Presenter
Описан в Design Patterns Нет

Model-View-Presenter (MVP) — шаблон проектирования, производный от MVC, который используется в основном для построения пользовательского интерфейса.

Элемент Presenter в данном шаблоне берёт на себя функциональность посредника (аналогично контроллеру в MVC) и отвечает за управление событиями пользовательского интерфейса (например, использование мыши) так же, как в других шаблонах обычно отвечает представление.

Описание шаблона

править

MVP — шаблон проектирования пользовательского интерфейса, который был разработан для облегчения автоматического модульного тестирования и улучшения разделения ответственности в презентационной логике (отделения логики от отображения):

  • Модель (англ. Model) предоставляет данные для пользовательского интерфейса.
  • Представление (англ. View) реализует отображение данных (Модели) и маршрутизацию пользовательских команд или событий Presenterʼу.
  • Presenter управляет Моделью и Представлением. Например извлекает данные из Модели и форматирует их для отображения в Представлении.

Обычно экземпляр Представления создаёт экземпляр Presenterʼа, передавая ему ссылку на себя. При этом Presenter работает с Представлением в абстрактном виде, через его интерфейс. Когда вызывается событие Представления, оно вызывает конкретный метод Presenterʼа, не имеющего ни параметров, ни возвращаемого значения. Presenter получает необходимые для работы метода данные о состоянии пользовательского интерфейса через интерфейс Представления и через него же передаёт в Представление данные из Модели и другие результаты своей работы.

public class MyModel
{
    private int _state = 0;
    public MyModel(int initState)
    {
        _state = initState;
    }
    public int getState()
    {
        return _state;
    }
}
public class MyView : IView
{
    private readonly MyPresenter presenter;
    public MyView()
    {
        presenter = new(this);
    }
}
public class MyPresenter
{
    private readonly IView _view;
    private readonly MyModel model = new(123);

    public MyPresenter(IView view)
    {
        _view = view;
    }
}

Количество логики, допустимой в Представлении, различается для разных реализаций.

С точки зрения многоуровневой модели приложений в ООП, Presenter может рассматриваться как самостоятельный уровень между уровнем приложения и уровнем пользовательского интерфейса. В структуре Решения Приложения, Согласно принципам ООП и SOLID, каждый слой должен быть отдельной сборкой или даже набором сборок. Пример выше не позволяет построить полностью абстрактную структуру, что нарушает принципы. Например, любое изменение в Model потребует перекомпиляции Презентера, а его компиляция потребует компиляции Представления. Для устранения таких зависимостей, нарушающих принципы абстракции, Презентер должен работать с Моделью и Представлением через их интерфейсы в отдельных сборках, сборки Модели, Презентера и Представления не должны иметь ссылок друг на друга. Создаются слои и внедряются зависимости в сборке Приложения. Например, метод Main(), который является точкой запуска консольного приложения.

namespace AssembleOfInterfaces 
{
    public interface IModel
    {
        IList<int> Numbers { get; }
        int Sum();
    }
    public interface IView
    {
        int ReadA();
        int ReadB();
        void WriteSum(int sum);
    }
}
using AssembleOfInterfaces;
namespace AssembleOfModel
{
    public class MyModel : IModel
    {
        public IList<int> Numbers { get; } = new List<int>();
        public int Sum() => Numbers.Sum();
    }
}
using AssembleOfInterfaces;
using static System.Console;
namespace AssembleOfView
{
    public class MyView : IView
    {
        public int ReadA()
        {
            Write("Коэффициент A: ");
            return int.Parse(ReadLine() ?? string.Empty);
        }

        public int ReadB()
        {
            Write("Коэффициент B: ");
            return int.Parse(ReadLine() ?? string.Empty);
        }

        public void WriteSum(int sum) => WriteLine($"Сумма коэффициентов = {sum}.");
    }
}
using AssembleOfInterfaces;
namespace AssembleOfPresenter
{
    public class MyPresenter
    {
        private readonly IView view;
        private readonly IModel model;

        public MyPresenter(IModel myModel, IView view)
        {
            this.view = view;
            model = myModel;
        }

        public void Start()
        {
            model.Numbers.Add(view.ReadA());
            model.Numbers.Add(view.ReadB());
            view.WriteSum(model.Sum());
        }
    }
}
using AssembleOfInterfaces;
using AssembleOfModel;
using AssembleOfView;
using AssembleOfPresenter;
namespace AssembleOfApplication
{
    public class App
    {
        public static void Main()
        {
            MyModel model = new();
            MyView view = new();
            MyPresenter presenter = new MyPresenter(model, view);
            presenter.Start();
        }
    }
}

Для тех же Модели и Презентера можно создать другое Представление. Например, Форма с двумя полями, двумя кнопками и лейблом для вывода результата. В начальном состоянии поля и кнопки отключены: Enabled=false. Code Behind формы:

using AssembleOfInterfaces;
using System;
using System.Threading;
using System.Windows.Forms;

namespace AssembleOfFormsView
{
    public partial class NumbersForm : Form, IView
    {
        public NumbersForm()
        {
            InitializeComponent();
            labelSum.Text = "0";
        }

        private readonly AutoResetEvent readAEvent = new AutoResetEvent(false);
        private readonly AutoResetEvent readBEvent = new AutoResetEvent(false);
        private int a, b;
        public int ReadA()
        {
            Invoke(new Action(() => textBoxA.Enabled = btnA.Enabled = true));
            readAEvent.WaitOne();
            return a;
        }


        public int ReadB()
        {
            Invoke(new Action(() => textBoxB.Enabled = btnB.Enabled = true));
            readBEvent.WaitOne();
            return b;
        }

        private void btnA_Click(object sender, EventArgs e)
        {
            a = int.Parse(textBoxA.Text);
            textBoxA.Enabled = btnA.Enabled = false;
            readAEvent.Set();
        }

        private void btnB_Click(object sender, EventArgs e)
        {
            b = int.Parse(textBoxB.Text);
            textBoxB.Enabled = btnB.Enabled = false;
            readBEvent.Set();
        }

        public void WriteSum(int sum)
        {
            Invoke(new Action(() => labelSum.Text = sum.ToString()));
        }
    }
}

Точка сборки:

using AssembleOfFormsView;
using AssembleOfModel;
using AssembleOfPresenter;
using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace App
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            MyModel model = new MyModel();
            NumbersForm view = new NumbersForm();
            MyPresenter presenter = new MyPresenter(model, view);

            view.Shown += async delegate { await Task.Run(presenter.Start); };

            Application.Run(view);

        }
    }
}

История

править

Эволюция и несколько вариантов шаблона MVP, в том числе отношения MVP с другими шаблонами проектирования (такими как MVC) были подробно проанализированы в статье Мартина Фаулера[1][2] , а также в статье Дерека Грира[3].

См. также

править

Примечания

править
  1. «GUI Architectures» Мартин Фаулер. Часть 1. Дата обращения: 30 мая 2012. Архивировано 11 марта 2013 года.
  2. «GUI Architectures» Мартин Фаулер. Часть 2. Дата обращения: 30 мая 2012. Архивировано 11 марта 2013 года.
  3. «Interactive Application Architecture Patterns» Derek Greer. Дата обращения: 30 мая 2012. Архивировано 30 мая 2012 года.

Ссылки

править

📚 Artikel Terkait di Wikipedia

POSIX

страниц. Заголовок обновлённого стандарта гласил: «Part 1: System Application Program Interface (API) [C Language]». Таким образом, было явно указано,

Windows 10

Дата обращения: 28 ноября 2017. Watch how Windows 10 works with touch interfaces. The Verge. Архивировано 8 января 2018. Дата обращения: 28 ноября 2017

Сети VANET

Intelligent Transport Systems in the field of road transport and for interfaces with other modes of transport (http://eur-lex.europa.eu/legal-content/EN/ALL/

Индуцированные стволовые клетки

Synthetic Scaffolds Based on Carbon Nanotubes. ACS Applied Materials & Interfaces,; 140123104241006 DOI:10.1021/am405097w Dixon, J. E., Shah, D. A., Rogers

Поиск сайтов связывания транскрипционных факторов in silico

database of transcription factors with annotated cis elements and binding interfaces.» Архивная копия от 11 декабря 2025 на Wayback Machine Bioinformatics