受け入れられた答えは、3つのケースしかなく、それぞれのロジックが単純な場合に問題ありません。
ただし、各ケースのロジックがより複雑である場合、またはさらに多くのケースがある場合は、責任の連鎖を使用する方がはるかに優れたオプションです。設計パターン。
へのBaseValidator
参照を含むを作成し、参照先のバリデーターの検証を呼び出すためのメソッドとBaseValidator
メソッドを作成しますvalidate
。
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;
}
}
次にBaseValidator
、から継承する多数のサブクラスを作成し、validate
各バリデータに必要なロジックでメソッドをオーバーライドします。
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);
}
}
次に、それを使用するのは簡単です。各バリデーターをインスタンス化し、それぞれを他のルートに設定します。
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)) { ... }
本質的に、各検証ケースには独自のクラスがあり、(a)検証がそのケースと一致するかどうかを判別し、(b)一致しない場合はチェーン内の他の誰かに検証を送信します。
私はC ++に慣れていないことに注意してください。オンラインで見つけたいくつかの例の構文と一致させようとしましたが、これが機能しない場合は、疑似コードのように扱います。また、必要に応じて基礎として使用できる完全な動作するPythonの例を以下に示します。
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))
繰り返しになりますが、特定の例ではこのやり過ぎが見つかるかもしれませんが、満たす必要のあるはるかに複雑なケースのセットになってしまうと、コードがよりクリーンになります。
if
ステートメントの代わりにテーブルを使用します。さらに、これらはブールフラグであるため、各シナリオを定数としてモデル化し、それをチェックできます。