La respuesta aceptada está bien cuando solo tiene 3 casos y donde la lógica para cada uno es simple.
Pero si la lógica para cada caso fuera más complicada, o hay muchos más casos, una opción mucho mejor es utilizar la cadena de responsabilidad. patrón de diseño de .
Creas un BaseValidator
que contiene una referencia a un BaseValidator
y un método validate
y un método para llamar a la validación en el validador al que se hace referencia.
class BaseValidator {
BaseValidator* nextValidator;
public:
BaseValidator() {
nextValidator = 0;
}
void link(BaseValidator validator) {
if (nextValidator) {
nextValidator->link(validator);
} else {
nextValidator = validator;
}
}
bool callLinkedValidator(bool v1, bool v2, bool v3, bool v4) {
if (nextValidator) {
return nextValidator->validate(v1, v2, v3, v4);
}
return false;
}
virtual bool validate(bool v1, bool v2, bool v3, bool v4) {
return false;
}
}
Luego, crea una serie de subclases que heredan de BaseValidator
, anulando el validate
método con la lógica necesaria para cada validador.
class Validator1: public BaseValidator {
public:
bool validate(bool v1, bool v2, bool v3, bool v4) {
if (v1 && v2 && v3 && v4) {
return true;
}
return nextValidator->callLinkedValidator(v1, v2, v3, v4);
}
}
Luego, usarlo es simple, cree una instancia de cada uno de sus validadores y configure cada uno de ellos para que sea la raíz de los demás:
Validator1 firstValidator = new Validator1();
Validator2 secondValidator = new Validator2();
Validator3 thirdValidator = new Validator3();
firstValidator.link(secondValidator);
firstValidator.link(thirdValidator);
if (firstValidator.validate(value1, value2, value3, value4)) { ... }
En esencia, cada caso de validación tiene su propia clase que es responsable de (a) determinar si la validación coincide con esa caso, y (b) enviar la validación a otra persona en la cadena si no lo es.
Tenga en cuenta que no estoy familiarizado con C ++. Intenté hacer coincidir la sintaxis de algunos ejemplos que encontré en línea, pero si esto no funciona, trátelo más como un pseudocódigo. También tengo un ejemplo completo de Python funcional a continuación que se puede usar como base si se prefiere.
class BaseValidator:
def __init__(self):
self.nextValidator = 0
def link(self, validator):
if (self.nextValidator):
self.nextValidator.link(validator)
else:
self.nextValidator = validator
def callLinkedValidator(self, v1, v2, v3, v4):
if (self.nextValidator):
return self.nextValidator.validate(v1, v2, v3, v4)
return False
def validate(self, v1, v2, v3, v4):
return False
class Validator1(BaseValidator):
def validate(self, v1, v2, v3, v4):
if (v1 and v2 and v3 and v4):
return True
return self.callLinkedValidator(v1, v2, v3, v4)
class Validator2(BaseValidator):
def validate(self, v1, v2, v3, v4):
if (v1 and v2 and v3 and not v4):
return True
return self.callLinkedValidator(v1, v2, v3, v4)
class Validator3(BaseValidator):
def validate(self, v1, v2, v3, v4):
if (v1 and not v2 and not v3 and not v4):
return True
return self.callLinkedValidator(v1, v2, v3, v4)
firstValidator = Validator1()
secondValidator = Validator2()
thirdValidator = Validator3()
firstValidator.link(secondValidator)
firstValidator.link(thirdValidator)
print(firstValidator.validate(False, False, True, False))
Nuevamente, puede encontrar esto excesivo para su ejemplo específico, pero crea un código mucho más limpio si termina con un conjunto de casos mucho más complicado que deben cumplirse.
if
declaración compleja . Además, como se trata de indicadores booleanos, puede modelar cada escenario como una constante y compararlo.