I'm currently trying a Password checker for password in Decorator Pattern, which will point out what the current password missing to be a strong password (my example will check for 8 characters, at least 1 uppercase, 1 lowercase, 1 number).
Please review and help to improve this code.
interface Password {
String getPassword();
boolean isValid();
String getValidationErrors();
}
class BasePassword implements Password {
private final String password;
public BasePassword(String password) {
this.password = password;
}
@Override
public String getPassword() {
return password;
}
@Override
public boolean isValid() {
return true;
}
@Override
public String getValidationErrors() {
return "";
}
}
abstract class PasswordDecorator implements Password {
protected final Password password;
public PasswordDecorator(Password password) {
this.password = password;
}
@Override
public String getPassword() {
return password.getPassword();
}
@Override
public abstract boolean isValid();
@Override
public String getValidationErrors() {
return password.getValidationErrors();
}
}
class MinLengthValidator extends PasswordDecorator {
private static final int MIN_LENGTH = 8;
public MinLengthValidator(Password password) {
super(password);
}
@Override
public boolean isValid() {
return password.getPassword().length() >= MIN_LENGTH;
}
@Override
public String getValidationErrors() {
String err = super.getValidationErrors();
if (!isValid()) {
err = err + "\n" + "+ Need at least 8 or more characters";
}
return err;
}
}
class UppercaseValidator extends PasswordDecorator {
public UppercaseValidator(Password password) {
super(password);
}
@Override
public boolean isValid() {
return password.getPassword().chars().anyMatch(Character::isUpperCase);
}
@Override
public String getValidationErrors() {
String err = super.getValidationErrors();
if (!isValid()) {
err = err + "\n" + "+ Need at least one uppercase character";
}
return err;
}
}
class NumberValidator extends PasswordDecorator {
public NumberValidator(Password password) {
super(password);
}
@Override
public boolean isValid() {
return password.getPassword().chars().anyMatch(Character::isDigit);
}
@Override
public String getValidationErrors() {
String err = super.getValidationErrors();
if (!isValid()) {
err = err + "\n" + "+ Need at least one number";
}
return err;
}
}
class LowercaseValidator extends PasswordDecorator {
public LowercaseValidator(Password password) {
super(password);
}
@Override
public boolean isValid() {
return password.getPassword().chars().anyMatch(Character::isLowerCase);
}
@Override
public String getValidationErrors() {
String err = super.getValidationErrors();
if (!isValid()) {
err = err + "\n" + "+ Need at least one lowercase character";
}
return err;
}
}
class PasswordValidator {
public static String validate(String password) {
Password decoratedPassword = new BasePassword(password);
decoratedPassword = new MinLengthValidator(decoratedPassword);
decoratedPassword = new UppercaseValidator(decoratedPassword);
decoratedPassword = new NumberValidator(decoratedPassword);
decoratedPassword = new LowercaseValidator(decoratedPassword);
return decoratedPassword.getValidationErrors();
}
}
public class Main {
public static void main(String[] args) {
String strongPassword = "StrongP@ss123";
String weakPassword = "weakpas";
System.out.println(PasswordValidator.validate(strongPassword)); //won't print anything
System.out.println(PasswordValidator.validate(weakPassword));
}
}
Optionalreturn value, which returns aStringif and only if it contains a valid password. Then, the password checks repeatedly apply.filterto theOptional<String>. \$\endgroup\$