强制执行类先决条件的Java设计模式

时间:2018-10-06 21:23:50

标签: java design-patterns

我想知道在构建时实施全班级先决条件的最佳设计是什么。

让我举一个简单的例子。

我有一个代表安全字符串的类,例如密码。密码仅存储为其哈希表示。密码无法检查,只能根据尝试输入的值进行检查。

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变量,因此所有密码实例的哈希值都相同。并设置了强制它一次不能更改的设置器。

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 :(得分:0)

我建议更改您的设计,并尝试以其他方式进行处理。 首先,进行一些重构。构造函数不应包含任何代码。其次,您可以创建一个哈希器接口。不过,我会将其重构为:

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);
    }
}

那将是一个优雅的设计。您只需要确保通过构造函数传递正确的哈希实现即可。设置好之后 每个密码将被验证为相同的实现。