La risposta accettata va bene quando hai solo 3 casi e dove la logica per ciascuno è semplice.
Ma se la logica per ogni caso fosse più complicata, o ci fossero molti più casi, un'opzione di gran lunga migliore sarebbe quella di utilizzare il modello di progettazione della catena di responsabilità .
Si crea un BaseValidatorche contiene un riferimento a BaseValidatore un metodo a validatee un metodo per chiamare la convalida sul validatore di riferimento.
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;
}
}
Quindi crei una serie di sottoclassi che ereditano da BaseValidator, sovrascrivendo il validatemetodo con la logica necessaria per ogni validatore.
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);
}
}
Quindi usarlo è semplice, istanzia ciascuno dei tuoi validatori e imposta ciascuno di essi come radice degli altri:
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)) { ... }
In sostanza, ogni caso di convalida ha la propria classe che è responsabile di (a) determinare se la convalida corrisponde a quella caso e (b) inviare la convalida a qualcun altro nella catena se non lo è.
Tieni presente che non ho familiarità con il C ++. Ho provato ad abbinare la sintassi da alcuni esempi che ho trovato online, ma se questo non funziona, trattalo più come uno pseudocodice. Di seguito ho anche un esempio completo di Python funzionante che può essere utilizzato come base se si preferisce.
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))
Di nuovo, potresti trovare questo eccessivo per il tuo esempio specifico, ma crea un codice molto più pulito se ti ritrovi con una serie di casi molto più complicata che devono essere soddisfatte.
ifdichiarazione complessa . Inoltre, poiché si tratta di flag booleani, è possibile modellare ogni scenario come una costante e confrontarlo.