Zaakceptowana odpowiedź jest dobra, gdy masz tylko 3 przypadki, a logika każdego z nich jest prosta.
Ale jeśli logika dla każdego przypadku byłaby bardziej skomplikowana lub jest o wiele więcej przypadków, znacznie lepszą opcją jest użycie wzorca projektowego łańcucha odpowiedzialności .
Tworzysz, BaseValidator
który zawiera odwołanie do a BaseValidator
i metodę do validate
oraz metodę do wywołania walidacji w walidatorze, do którego się odwołuje.
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;
}
}
Następnie tworzysz kilka podklas, które dziedziczą BaseValidator
po validate
metodzie , nadpisując metodę logiką niezbędną dla każdego walidatora.
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);
}
}
Następnie użycie go jest proste, utwórz instancję każdego ze swoich walidatorów i ustaw każdy z nich jako katalog główny pozostałych:
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)) { ... }
Zasadniczo każdy przypadek walidacji ma swoją własną klasę, która jest odpowiedzialna za (a) określenie, czy walidacja pasuje do tego przypadku i (b) wysłanie walidacji do kogoś innego w łańcuchu, jeśli tak nie jest.
Zwróć uwagę, że nie znam C ++. Próbowałem dopasować składnię z kilku przykładów, które znalazłem online, ale jeśli to nie zadziała, potraktuj to bardziej jak pseudokod. Poniżej mam również kompletny działający przykład Pythona, który można wykorzystać jako podstawę, jeśli jest to preferowane.
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))
Ponownie, możesz znaleźć to przesadę w swoim konkretnym przykładzie, ale tworzy znacznie czystszy kod, jeśli skończysz z dużo bardziej skomplikowanym zestawem przypadków, które należy spełnić.
if
instrukcji. Dodatkowo, ponieważ są to flagi logiczne, możesz modelować każdy scenariusz jako stałą i porównywać z nią.