Skip to content

Instantly share code, notes, and snippets.

@talhaHavadar
Last active August 18, 2021 10:10
Show Gist options
  • Save talhaHavadar/e5fbb8b28dc30f657c666efbbca9bcab to your computer and use it in GitHub Desktop.
Save talhaHavadar/e5fbb8b28dc30f657c666efbbca9bcab to your computer and use it in GitHub Desktop.
Cpp Validator Pattern to reduce if statements in code. #chainofresponsibility, #validatorpattern, #cpp, #validator
#ifndef MODELVALIDATOR_H
#define MODELVALIDATOR_H
#include "memory"
#include <QList>
using namespace std;
enum class ModelType
{
PERSON,
CAR
};
class Model
{
public:
Model(const ModelType& type): m_type{type} {}
const ModelType& type() const { return m_type; }
private:
ModelType m_type;
};
class PersonModel: public Model
{
public:
PersonModel(const quint8 age, const QString& name):
Model(ModelType::PERSON), m_age{age}, m_name{name} {}
virtual ~PersonModel() {}
void setAge(const quint8& age) { m_age = age; }
const quint8& age() const { return m_age; }
const QString& name() const { return m_name; }
private:
quint8 m_age;
QString m_name;
};
enum class CarColor
{
RED,
GREEN,
BLUE
};
class CarModel: public Model
{
public:
CarModel(quint32 wheelCount, quint32 maxSpeed, CarColor color):
Model(ModelType::CAR), m_wheelCount{wheelCount}, m_maxSpeed{maxSpeed}, m_color{color} {}
const quint32& wheelCount() const { return m_wheelCount; }
const quint32& maxSpeed() const { return m_maxSpeed; }
const CarColor& color() const { return m_color; }
private:
quint32 m_wheelCount;
quint32 m_maxSpeed;
CarColor m_color;
};
typedef function<bool(Model&)> RuleFunction;
typedef function<void(Model&)> ActionFunction;
class ModelValidator {
public:
ModelValidator() {
m_chain = new QList<RuleFunction>();
};
virtual ~ModelValidator() {
m_chain->clear();
delete m_chain;
}
ModelValidator& rule(const RuleFunction& func) {
m_chain->push_back(func);
return *this;
}
bool apply(Model& m) {
bool result = true;
for (auto& func: *m_chain)
{
result = func(m);
if (!result)
{
if (m_onFailure)
{
(*m_onFailure)(m);
}
break;
}
}
if (result)
{
(*m_onSuccess)(m);
}
return result;
}
ModelValidator& onFailure(const ActionFunction& func) {
m_onFailure = make_unique<ActionFunction>(func);
return *this;
}
ModelValidator& onSuccess(const ActionFunction& func) {
m_onSuccess = make_unique<ActionFunction>(func);
return *this;
}
private:
QList<RuleFunction>* m_chain;
unique_ptr<ActionFunction> m_onFailure;
unique_ptr<ActionFunction> m_onSuccess;
};
template <typename M>
class ModelTemplateValidator {
public:
ModelTemplateValidator() {
m_chain = new QList<function<bool(M&)>>();
};
virtual ~ModelTemplateValidator() {
m_chain->clear();
delete m_chain;
}
ModelTemplateValidator& rule(const function<bool(M&)>& func) {
m_chain->push_back(func);
return *this;
}
bool apply(M& m) {
bool result = true;
for (auto& func: *m_chain)
{
result = func(m);
if (!result)
{
if (m_onFailure)
{
(*m_onFailure)(m);
}
break;
}
}
if (result)
{
(*m_onSuccess)(m);
}
return result;
}
ModelTemplateValidator& onFailure(const function<void(M&)>& func) {
m_onFailure = make_unique<function<void(M&)>>(func);
return *this;
}
ModelTemplateValidator& onSuccess(const function<void(M&)>& func) {
m_onSuccess = make_unique<function<void(M&)>>(func);
return *this;
}
private:
QList<function<bool(M&)>>* m_chain;
unique_ptr<function<void(M&)>> m_onFailure;
unique_ptr<function<void(M&)>> m_onSuccess;
};
#endif // MODELVALIDATOR_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment