шаблон проектирования Java для обеспечения обязательных условий класса - PullRequest
0 голосов
/ 07 октября 2018

Мне интересно, каков наилучший дизайн для общеклассового обязательного условия, которое должно соблюдаться во время строительства.

Позвольте мне привести упрощенный пример.

У меня есть класс, представляющий безопасную строку, например, пароль.Пароли хранятся только как их хэш-представление.Пароли не могут быть проверены, но проверяются только на предмет попытанного значения.

class Password {
  private String passwordHash;
  private Password(){};
  public Password(String aPassword) {
    setPassword(aPassword);
  }
  public void setPassword(String aPassword) {
     passwordHash = hash(aPassword); 
  }
  public boolean checkPassword(String attempt) {
     return verify(attempt, passwordHash);
  }
} 

Вопрос в том, как спроектировать выбор алгоритма хеширования.Код клиента должен иметь возможность выбирать из различных алгоритмов хеширования.И в данном приложении все пароли должны использовать один и тот же алгоритм хеширования.

Итак, я определяю интерфейс Hasher,

interface Hasher {
  String hash(String password);
  boolean verify(String attempt, String hash);
}

Могут быть разные реализации Hasher.

class SimpleHasher implements Hasher {
  public String hash(String password) {  // native java String.hashCode()  
    return Integer.toString(password.hashCode(),16);
  }
  public boolean verify(String attempt, String hash) {
    return attempt.hashCode()==Integer.valueOf(hash, 16);
  }  
}

class SecureHasher implements Hasher {
  public String hash(String password) {  // Secure SCrypt hash
    return com.lambdaworks.crypto.SCryptUtil.scrypt(password,16384,8,1);
  }
  public boolean verify(String attempt, String hash) {
    return com.lambdaworks.crypto.SCryptUtil.check(attempt,hash);
  }
}

Код клиента должен выбрать реализацию и установить хеш-код.До тех пор никто не может создать пароль.И после установки хеш не может быть изменен.

Вот проектное решение.

В настоящее время я объявляю переменную static private, поэтому хеш-код одинаков для всех экземпляров Password;и устанавливается установщик, который принудительно запрещает его однократное изменение.

class Password {
  static private Hasher hasher = null;
  static public void setHasher(Hasher ahasher) throws Exception {
    if (hasher!=null) throw new Exception("hasher cannot be changed");
    hasher = ahasher;
  } 
  ....      

, а конструктор гарантирует, что пока хеш установлен

class Password {
   ...    
   public Password(String aPassword) throws Exception {
     if (hasher==null) throw new Exception("no hasher set yet");  
     setPassword(aPassword);
   } 
   ...       

, так хорошо.Но, на мой взгляд, это выглядит не очень хорошо.Интересно, есть ли какой-то общий шаблон для решения этой проблемы.Поэтому мой вопрос заключается в том, существует ли такая модель и как ее можно реализовать в моем случае.

1 Ответ

0 голосов
/ 07 октября 2018

Я бы предложил изменить ваш дизайн и попытаться подойти к нему немного иначе.Прежде всего, сделайте рефакторинг.Конструктор не должен содержать никакого кода.Во-вторых, здорово, что вы делаете интерфейс хеша.Тем не менее, я бы изменил его на:

public interface Hash {
    String hashed(String value);
    boolean isValid(String hashed);
}  

Затем измените ваш класс пароля:

public class Password {

    private String password;
    private Hash hash;

    public Password(String password, Hash hash) {
        this.password = password;
        this.hash = hash;
    }

    public boolean isValid(String password) {
       return hash.hashed(this.password).equals(hash.hashed(password);
    }
}

Это будет элегантный дизайн.Вам просто нужно убедиться, что правильная реализация хеша передается через конструктор.Как только это будет установлено, каждый пароль будет проверен на ту же реализацию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...