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

MVP паттерн

23.05.2024, 14:53. Показов 439. Ответов 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 (объединенное свойство). Это тема моей...

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

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

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

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

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

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

Паттерн декоратор
доброго времени суток уважаемые форумчане, помогите пожалуйста разобраться, где я допустил ошибку? ...

Паттерн Builder
Вот у меня есть код примера реализации паттерна Builder(другие примеры не предлагать). В классе...


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

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Новые блоги и статьи
Проектирование и моделирование
hw_wired 28.01.2025
Введение в моделирование Моделирование представляет собой один из фундаментальных методов научного познания, который позволяет изучать объекты и явления через создание их упрощенных аналогов. В. . .
Алгоритмы и исполнители
hw_wired 28.01.2025
Введение в алгоритмы В современном мире информационных технологий алгоритмы играют основополагающую роль в решении различных задач и автоматизации процессов. Алгоритм представляет собой точную. . .
Хранение информации
hw_wired 28.01.2025
Введение: Роль систем хранения информации в современном мире В современную эпоху цифровых технологий эффективное хранение информации становится одним из ключевых факторов успешного развития любой. . .
Обработка числовой информации
hw_wired 28.01.2025
Введение в обработку числовой информации В современном мире обработка числовой информации стала неотъемлемой частью как профессиональной деятельности, так и повседневной жизни. Электронные таблицы. . .
Мультимедиа
hw_wired 28.01.2025
Введение в мультимедийные технологии В современном мире мультимедийные технологии стали неотъемлемой частью нашей жизни, проникнув во все сферы человеческой деятельности. Термин "мультимедиа". . .
Обработка текстовой информации
hw_wired 28.01.2025
Введение в обработку текстовой информации В современном мире обработка текстовой информации играет фундаментальную роль в различных сферах человеческой деятельности. Текстовые редакторы стали. . .
Обработка графической информации
hw_wired 28.01.2025
Введение в компьютерную графику Компьютерная графика стала неотъемлемой частью современного цифрового мира, пройдя впечатляющий путь развития от простейших черно-белых изображений до сложных. . .
Python в Алгоритмике: Решение задач
hw_wired 28.01.2025
Введение в Python и Алгоритмику В современном мире программирование стало неотъемлемой частью образования и профессионального развития. Python зарекомендовал себя как один из самых популярных и. . .
Компьютер как универсальное устройство для работы с информацией
hw_wired 28.01.2025
Введение в устройство компьютера Компьютер представляет собой универсальное электронное устройство, предназначенное для автоматической обработки информации. В современном мире компьютер стал. . .
Информация и информационные процессы
hw_wired 28.01.2025
Понятие информации и ее виды В современном мире информация является одним из фундаментальных понятий, пронизывающих все сферы человеческой деятельности. Под информацией понимают любые сведения об. . .
Алгоритмика
hw_wired 28.01.2025
Введение: Основы алгоритмики и её роль в информатике В современном мире программирование и алгоритмическое мышление стали неотъемлемой частью образования и профессиональной деятельности. . . .
Информационное моделирование
hw_wired 28.01.2025
Введение в информационное моделирование В современном мире информационное моделирование стало неотъемлемой частью научной, образовательной и профессиональной деятельности. Это мощный инструмент. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru