Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 09.01.2023
Сообщений: 33
1

MVP паттерн

23.05.2024, 14:53. Показов 454. Ответов 0
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день,
В качестве практики решил попробовать реализовать MVP паттерн для создание сложных UI элементов. При попытке найти что-то в интернете в основном попадается либо C#, либо QT на ++.
Вроде как все получилось и даже работает, но не могу понять, как можно реализовать нормальную передачу значений между представлением и моделью (сейчас они работаю через общий унаследованный класс с абстрактным методом перевода строки в значение), чтобы представитель все также мог внутри себя содержать абстракции. Также возникают сомнения в правильности реализации.

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

файл.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <list>
 
class ViewBase;
class ModelBase;
class PresenterBase {
protected:
    std::list<ViewBase*> _views;
    ModelBase *_model;
    virtual ViewBase* CreateViewImpl() = 0;
public:
    PresenterBase(ModelBase *_model);
    ViewBase* CreateView();
    virtual void UpdateModel(ViewBase *sender) = 0;
};
 
class TextBoxPresenter: public PresenterBase {
protected:
    virtual ViewBase* CreateViewImpl() override;
public:
    using PresenterBase::PresenterBase;
    virtual void UpdateModel(ViewBase *sender) override;
};
файл.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "presenter.h"
#include "view.h"
#include "model.h"
#include <wx/log.h>
 
// Конструктор
PresenterBase::PresenterBase(ModelBase *model)
: _model(model) { }
 
// Создать представление
ViewBase* PresenterBase::CreateView() {
    ViewBase* view = CreateViewImpl();
    view->Subscribe(this);
    _views.push_front(view);
    return view;
}
 
// Создать конкретный экземпляр представления
ViewBase* TextBoxPresenter::CreateViewImpl() {
    return new TextBoxView();
}
 
// Алгоритм обновления модели 
void TextBoxPresenter::UpdateModel(ViewBase *sender) {
    if(_model->GetState()) {
        _model->SetState(false);
        std::string value = sender->GetValue();
        _model->SetValue(value);
        for(auto &view : _views) {
            if(view != sender) {
                view->SetValue(value);
            }
        }
        _model->SetState(true);
        wxLogMessage(wxString::Format("Send data to database\n\tID: %s,\n\tValue: %s", _model->GetID(), _model->GetValue()));
    }
 
}
Представление в свою очередь наследует UI панель (на которой будут располагаться какие-нибудь простые UI элементы) и также наследует абстрактный класс, который выполняет перевод значения в строку.
Для добавление нового класса представления мне достаточно переопределить метод создания сложного UI объекта с указанием родителя к которому он принадлежит (окно, панель и т.д.) и также переопределить методы для конвертации значения в строку:

файл.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "data_base_value.h"
#include <wx/panel.h>
#include <wx/textctrl.h>
#include <wx/window.h>
 
class PresenterBase;
class ViewBase: public DataBaseValue, public wxPanel {
protected:
    friend class PresenterBase;
    PresenterBase *_presenter;
    void Subscribe(PresenterBase *presenter);
public:
    virtual void Create(wxWindow *parent) = 0;
};
 
class TextBoxView: public ViewBase {
private:
    wxTextCtrl *_text;
public:
    virtual void Create(wxWindow *parent) override;
    virtual void SetValue(std::string const &value) override;
    virtual std::string GetValue() const override;
};
файл.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include "view.h"
#include "presenter.h"
#include <wx/stattext.h>
#include <wx/sizer.h>
 
// Указать представителя
void ViewBase::Subscribe(PresenterBase *presenter) {
    _presenter = presenter;
}
 
// Создать представление
void TextBoxView::Create(wxWindow *parent) {
 
    // Создать панель
    wxPanel::Create(parent);
 
    // Создать элементы
    _text = new wxTextCtrl(this, wxID_ANY);
    wxStaticText *label = new wxStaticText(this, wxID_ANY, L"Текстовое поле:");
 
    // Создать макет для панели
    wxBoxSizer *this_sizer = new wxBoxSizer(wxHORIZONTAL);
    this_sizer->Add(label, 1);
    this_sizer->Add(_text, 1);
    SetSizerAndFit(this_sizer);
 
    // Создать событие
    _text->Bind(wxEVT_TEXT,
        [&](wxCommandEvent&) {
            if(_presenter) {
                _presenter->UpdateModel(this);
            }
        }
    );
}
 
// Указать значение (для работы с общим видом данных)
void TextBoxView::SetValue(std::string const &value) {
    _text->SetValue(wxString(value));
}
 
// Получить значение (для работы с общим видом данных)
std::string TextBoxView::GetValue() const {
    return _text->GetValue().ToStdString();
}
Модель данных содержит информацию о ее идентификаторе (который ассоциирует модель с конкретным значением в базе данных) и состоянии.
Модель также, как и представление наследует абстрактный класс для перевода значения в строку и для создание нового класса модели необходимо переопределить только эти два метода:

файл.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string>
#include "data_base_value.h"
 
class ModelBase: public DataBaseValue {
private:
    std::string _id;
    bool _state;
public:
    ModelBase(std::string const &id);
    std::string GetID() const;
    void SetState(bool state);
    bool GetState() const;
};
 
class StringModel: public ModelBase {
private:
    std::string _value;
public:
    StringModel(std::string const &id, std::string const &value = std::string());
    virtual void SetValue(std::string const &value) override;
    virtual std::string GetValue() const override;
};
файл.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "model.h"
 
// Конструктор
ModelBase::ModelBase(std::string const &id)
: _id(id),
_state(true) { }
 
// Получить идентификатор
std::string ModelBase::GetID() const {
    return _id;
}
 
// Установить состояние
void ModelBase::SetState(bool state) {
    _state = state;
}
 
// Получить состояние
bool ModelBase::GetState() const {
    return _state;
}
 
// Конструктор строковой модели
StringModel::StringModel(std::string const &id, std::string const &value)
: ModelBase(id),
_value(value) { }
 
// Указать занчение (для работы с общим видом данных)
void StringModel::SetValue(std::string const &value) {
    _value = value;
}
 
// получить занчение (для представления)
std::string StringModel::GetValue() const {
    return _value;
}
Вспомогательный абстрактный класс для работы со значениями модели и представления при помощи строк:

файл.h
C++
1
2
3
4
5
6
7
#include <string>
 
class DataBaseValue {
public:
    virtual void SetValue(std::string const &value) = 0;
    virtual std::string GetValue() const = 0;
};


Правка
Забыл добавить собственно создание представителя и добавление представлений на форму
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "app.h"
#include "view.h"
#include "model.h"
#include "presenter.h"
#include <wx/frame.h>
#include <wx/sizer.h>
 
class Frame: public wxFrame {
private:
    TextBoxPresenter *_text_box_preseter;
public:
    Frame()
        : wxFrame(nullptr, wxID_ANY, "Title") {
        // Создать представителя
        _text_box_preseter = new TextBoxPresenter(new StringModel("id_database_text_field"));
 
        // Создать представления
        ViewBase *f1 = _text_box_preseter->CreateView();
        ViewBase *f2 = _text_box_preseter->CreateView();
        ViewBase *f3 = _text_box_preseter->CreateView();
 
        // Добавить представления к форме
        f1->Create(this);
        f2->Create(this);
        f3->Create(this);
 
        // Создать макет формы
        wxBoxSizer *this_sizer = new wxBoxSizer(wxVERTICAL);
        this_sizer->Add(f1, 1);
        this_sizer->Add(f2, 1);
        this_sizer->Add(f3, 1);
        SetSizerAndFit(this_sizer);
    }
};
 
bool Application::OnInit() {
    Frame *f = new Frame();
    f->Show();
    return true;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.05.2024, 14:53
Ответы с готовыми решениями:

Паттерн стратегия
Всем привет! Начал изучать паттерны. Одним из наиболее понятных и интересных мне оказался паттерн Стратегия. Я начитался статей и...

Паттерн Singleton
Здравствуйте. Например есть класический одиночка и загрузка музыки. Возможно ли сделать загрузку и вопроизведение музыки через класс...

Паттерн Embedded Value
Доброго времени суток, вопрос по паттерну Embedded Value (объединенное свойство). Это тема моей курсовой, нашел про него немного теории, да...

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.05.2024, 14:53
Помогаю со студенческими работами здесь

Паттерн Singleton
Мне вот дали такой код как паттерн Singleton: #include &quot;stdafx.h&quot; template &lt;class T&gt; class SingletonS { static int...

Паттерн Мост
Спроектировать приложение, которое позволяет создавать пиццу с произвольным количеством ингредиентов. Предусмотреть два вида основ для...

Паттерн Singleton
Здравствуйте, уважаемые участники форума Столкнулся с проблемой Имеется клиентское приложение, написанное в QT Creator для соединения...

Паттерн Decorator
Всем привет. Нужен маскимально простенький код или несколько кодов для пояснения Декоратора( его работы и особенности ). На языке С++...

паттерн и строка C++
Возникла необходимость производить поиск в строке по паттерну, который может содержать символ '*' и '?'.Например: искать в строке...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Новые блоги и статьи
Winforstrap или красявый дизайн своими руками на HTML+JS+Winform­s
anomal6 04.03.2025
Сидел тут вечером ковырял проект на MAUI, и как же глупо создаются пакеты MSIX и система обновлений пакета публикации, но не об этом. Бывает нужен современный дизайн программы а писать на MAUI,. . .
Формат данных для симуляции физики, посредством распространённы­­­­­­­х не обученных моделей.
Hrethgir 04.03.2025
Что-то как-то снова потерялось, зато катангенсы закатангесились в одном сообщении. На днях писал, что планирую для работы апгрейдить (на этот раз удачно) девайс для работы (конкретно - здоровья для,. . .
Концепция variadic
CoderHuligan 04.03.2025
Мне не очень нравится (а кому это нравится?) что у нас есть отдельно компилятор, отдельно линковщик, причем со своим собственным командным языком. При этом усложнении надо знать помимо языка. . .
Java Record или Kotlin Data Class: что лучше для неизменяемых данных
Wired 04.03.2025
Java Record и Kotlin Data Class — два мощных инструмента для обуздания неизменяемых структур данных, каждый со своим уникальным подходом к решению этой задачи. История их появления весьма. . .
Создание производительны­­­х API с Java и gRPC
Wired 04.03.2025
В мире микросервисной разработки вопрос производительности часто становится краеугольным камнем. И хотя REST API давно завоевал сердца разработчиков своей простотой и интуитивностью, при высоких. . .
Что нового в JDK 24
Wired 04.03.2025
JDK 24 — это настоящий прорыв в эволюции Java, который кардинально меняет правила игры. В этом релизе разработчики Oracle наконец-то довели до ума множество критически важных улучшений в. . .
Разработка блокчейн с использованием Java: смарт-контракты и dApp
Wired 04.03.2025
Погружаясь в мир блокчейн-разработки на Java, разработчик получает доступ к внушительному арсеналу инструментов. В отличие от Solidity, который "заперт" в экосистеме Ethereum, Java предоставляет. . .
WebAssembly в Kubernetes
stackOverflow 03.03.2025
В современной экосистеме облачных технологий WebAssembly (Wasm) становится все более значимым компонентом, предлагая уникальный подход к выполнению кода в распределенных системах. Эта технология. . .
GitHub Actions или Jenkins: Выбираем CI/CD платформу
stackOverflow 03.03.2025
Непрерывная интеграция и развертывание (CI/ CD) изменили подход к разработке программного обеспечения, превратив его в бесшовный процесс от написания кода до развертывания в продакшн. GitHub Actions и. . .
Автоматизация тестирования Pull Request в Kubernetes: Интеграция с GitHub Actions и GKE
stackOverflow 03.03.2025
Масштабные проекты с использованием Kubernetes требуют надежной системы тестирования изменений перед их внедрением в продакшн-среду. Традиционный подход с ручной проверкой Pull Request не справляется. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru