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 BaseValidatorque contiene una referencia a un BaseValidatory un método validatey 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 validatemé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.
ifdeclaración compleja . Además, como se trata de indicadores booleanos, puede modelar cada escenario como una constante y compararlo.