i am asking me if this is a good design. I have my own variables which will be persisted on a server with legacy protocol. Is this the way to go in modern c++? Can i improve code with template, CRTP or std::variant?
I tried std::variant but with std::refrence_wrapper<connected_int32/connected_string> in std::vector i was not able to use std::find_if.
#include <algorithm>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
class mediator_interface
{
public:
virtual ~mediator_interface() noexcept = default;
void value_to_server(const uint32_t id, const std::vector<uint8_t> &value) noexcept { value_to_server_impl(id, value); }
void value_to_parameter(const uint32_t id, const std::vector<uint8_t> &value) noexcept { value_to_parameter_impl(id, value); }
private:
virtual void value_to_server_impl(const uint32_t id, const std::vector<uint8_t> &value) = 0;
virtual void value_to_parameter_impl(const uint32_t id, const std::vector<uint8_t> &value) = 0;
};
class parameter
{
public:
std::string_view topic() const noexcept { return topic_; }
void set_topic(const std::string_view topic) noexcept { topic_ = topic; }
uint32_t id() const noexcept { return id_; }
void set_id(const uint32_t id) noexcept { id_ = id; }
void set_mediator(mediator_interface *mediator_ptr) noexcept { mediator_ptr_ = mediator_ptr; }
virtual void set_value_impl(const std::vector<uint8_t> &value) = 0;
virtual void print_impl() = 0;
protected:
std::string_view topic_{""};
uint32_t id_{UINT32_MAX};
mediator_interface *mediator_ptr_{nullptr};
};
class connected_int32 final : public parameter
{
public:
connected_int32(const std::string_view topic) noexcept { topic_ = topic; }
int32_t value() const noexcept { return data_; }
void set_value_impl(const int32_t value) noexcept {
data_ = value;
if (mediator_ptr_) {
std::vector<uint8_t> tmp(sizeof(data_));
memcpy(tmp.data(), &data_, sizeof(data_));
mediator_ptr_->value_to_server(id_, tmp);
}
}
void set_value_impl(const std::vector<uint8_t> &value) noexcept { std::memcpy(&data_, value.data(), sizeof(data_)); }
void print_impl() { std::cout << "id: " << id_ << " --> value: " << data_ << std::endl; }
private:
int32_t data_ = 2;
};
class connected_string final : public parameter
{
public:
connected_string(const std::string_view topic) noexcept { topic_ = topic; }
std::string value() const noexcept { return data_; }
void set_value_impl(const std::string_view value) noexcept {
data_ = value;
if (mediator_ptr_) {
mediator_ptr_->value_to_server(id_, { data_.begin(), data_.end() });
}
}
void set_value_impl(const std::vector<uint8_t> &value) noexcept { data_ = std::string(value.begin(), value.end()); }
void print_impl() { std::cout << "id: " << id_ << " --> value: " << data_ << std::endl; }
private:
std::string data_ = "two";
};
class mediator final : public mediator_interface
{
public:
mediator() = default;
~mediator() = default;
void register_parameter(parameter *param) {
parameters_.push_back(param);
param->set_mediator(this);
}
bool receive_id(const std::string_view topic, uint32_t id) {
auto param = std::find_if(
std::begin(parameters_),
std::end(parameters_),
[&](const parameter *const p)
{
return p->topic() == topic;
});
if (param != std::end(parameters_))
{
(*param)->set_id(id);
return true;
}
return false;
}
void value_to_parameter_impl(const uint32_t id, const std::vector<uint8_t> &value) noexcept override {
auto param = std::find_if(
std::begin(parameters_),
std::end(parameters_),
[&](const parameter *const p)
{
return p->id() == id;
});
if (param != std::end(parameters_))
{
(*param)->set_value_impl(value);
}
}
void print_all() {
for (auto &e : parameters_) { e->print_impl(); }
}
private:
std::vector<parameter*> parameters_;
void value_to_server_impl(const uint32_t id, const std::vector<uint8_t> &value) noexcept override {
std::cout << "Sending data from id(" << id << ") to server..." << std::endl;
}
};
int main()
{
connected_int32 my_int{"TstInt"};
connected_string my_string{"TstString"};
mediator medi;
medi.register_parameter(&my_int);
medi.register_parameter(&my_string);
medi.print_all();
medi.receive_id("TstInt", 123);
medi.receive_id("TstString", 321);
medi.print_all();
//User updates variables, persisting to server...
my_int.set_value_impl(1);
my_string.set_value_impl("one");
medi.print_all();
//Getting update from server...
medi.value_to_parameter_impl(123, { 0, 0, 0, 0});
medi.value_to_parameter_impl(321, { 'z', 'e', 'r', 'o'});
medi.print_all();
}
Aucun commentaire:
Enregistrer un commentaire