Last active
August 18, 2021 10:10
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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