Gosto de usar uma abordagem com interfaces. Deixa o código mais fácil de fazer manutenção, evoluir, testar, etc.:
AuthenticityCodeGenerator
@FunctionalInterface
public interface AuthenticityCodeGenerator {
String generate(DataAuthenticityCode data);
}
UUIDAuthenticityCodeGenerator
import java.nio.ByteBuffer;
import java.util.UUID;
public class UUIDAuthenticityCodeGenerator implements AuthenticityCodeGenerator {
@Override
public String generate(DataAuthenticityCode data) {
ByteBuffer byteBuffer = ByteBuffer.allocate(Long.BYTES);
return UUID.nameUUIDFromBytes(byteBuffer.putLong(data.hashCode()).array()).toString();
}
}
Sha256AuthenticityCodeGenerator
import java.security.MessageDigest;
public class Sha256AuthenticityCodeGenerator implements AuthenticityCodeGenerator {
@Override
public String generate(DataAuthenticityCode data) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(String.valueOf(data.hashCode()).getBytes("UTF-8"));
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch(Exception ex) {
return null;
}
}
}
DataAuthenticityCode
@FunctionalInterface
public interface DataAuthenticityCode {
String generateAuthenticityCode(AuthenticityCodeGenerator generator);
}
User
import java.util.Objects;
public class User implements DataAuthenticityCode {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void changeLastname(String newLastname) {
this.lastName = newLastname;
}
@Override
public String generateAuthenticityCode(AuthenticityCodeGenerator generator) {
return generator.generate(this);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
}
Main
public class DataAuthenticityMain {
public static void main(String[] args) {
AuthenticityCodeGenerator generator = new UUIDAuthenticityCodeGenerator();
AuthenticityCodeGenerator sha256Generator = new Sha256AuthenticityCodeGenerator();
User user = new User("John", "Does");
System.out.println("UUID: " + user.generateAuthenticityCode(generator));
System.out.println("sha256: " + user.generateAuthenticityCode(sha256Generator));
user.changeLastname("Fulano");
System.out.println("UUID: " + user.generateAuthenticityCode(generator));
System.out.println("sha256: " + user.generateAuthenticityCode(sha256Generator));
}
}
Coloquei a classe Sha256AuthenticityCodeGenerator apenas para exemplificar como seria mais simples adicionar um mecanismo de gerar hash usando interfaces (não é o foco do seu post, mas talvez seja bom olhar por esse lado tb).
Os nomes das classes ficaram meio confusos. Tenho certa dificuldade de nomear classes =/