編寫一個驗證密碼強度的程序,能夠根據預先定義的規則,按各類排列組合來設定密碼的強度。
最小要求,每一個密碼都必須知足最小長度要求。
額外要求,能夠添加其餘規則限制,例如:c++
熟悉設計模式的讀者確定知道,這裏描述的問題是一個典型的裝飾器(Decorator)模式問題。
裝飾器模式在不改變現有對象結構的狀況下,動態地給該對象增長一些行爲,而不會影響相同類型的其餘對象。git
採用裝飾器模式擴展對象的功能比採用繼承方式更加靈活。
能夠設計出多個不一樣的具體裝飾類,創造出多個不一樣行爲的組合。設計模式
裝飾器模式增長了許多子類,過分使用會使程序變得很複雜。ide
多個裝飾器能夠彼此疊加,每次添加新功能。 在這個案例中,驗證給定密碼是否符合特定組合的要求。spa
先看看整個validating passwords
模型
設計
struct Validator { virtual ~Validator() {} virtual bool validate(std::string_view) = 0; };
基類Validator
定義了契約方法validate
,帶有表示密碼的字符串參數。c++11
struct LengthValidator final : Validator { LengthValidator(unsigned int length) : length_{length} {} bool validate(std::string_view password) override { return password.length() >= length_; } private: unsigned int length_; };
子類LengthValidator
實現了密碼最小長度的強制性要求。code
struct ValidatorDecorator : Validator { explicit ValidatorDecorator(std::unique_ptr<Validator> validator) : impl_(std::move(validator)) {} virtual bool validate(std::string_view password) override { return impl_->validate(password); } private: std::unique_ptr<Validator> impl_; };
數字密碼校驗對象
struct DigitalPasswordValidator final : ValidatorDecorator { explicit DigitalPasswordValidator(std::unique_ptr<Validator> validator) : ValidatorDecorator(std::move(validator)) {} bool validate(std::string_view password) override { if (!ValidatorDecorator::validate(password)) return false; return password.find_first_of("0123456789") != std::string::npos; } };
大小寫字母校驗blog
struct CasePasswordValidator final : ValidatorDecorator { explicit CasePasswordValidator(std::unique_ptr<Validator> validator) : ValidatorDecorator(std::move(validator)) {} bool validate(std::string_view password) override { if (!ValidatorDecorator::validate(password)) return false; bool has_lower = false; bool has_upper = false; std::for_each(begin(password), end(password), [&](const auto ch) { if (islower(ch)) has_lower = true; else if (isupper(ch)) has_upper = true; }); return has_lower && has_upper; } };
特殊符號校驗
struct SymbolPasswordValidator final : ValidatorDecorator { explicit SymbolPasswordValidator(std::unique_ptr<Validator> validator) : ValidatorDecorator(std::move(validator)) {} bool validate(std::string_view password) override { if (!ValidatorDecorator::validate(password)) return false; return password.find_first_of("`~!@#$%^&*-_=+(){}[]?<>,./") != std::string::npos; } };
最後舉個簡單的例子
int main() { auto validator = std::make_unique<LengthValidator>(8); auto num_validator = std::make_unique<DigitalPasswordValidator>(std::move(validator)); assert(num_validator->validate("abcd123,./")); assert(!num_validator->validate("abcdvdfs,./")); auto num_symbol_case_validator = std::make_unique<DigitalPasswordValidator>( std::make_unique<SymbolPasswordValidator>( std::make_unique<CasePasswordValidator>( std::make_unique<LengthValidator>(8)))); assert(num_symbol_case_validator->validate("Abc123!@#")); assert(!num_symbol_case_validator->validate("Abc12")); return 0; }