Looking for the name of the design pattern by which you have a POJO with public final "properties" where the property acts as a holder/wrapper for a certain type of value and contains the getter/setter for that value as well as potentially some additional logic.
This differs from the "Property Container" design pattern where you have a single properties container which contains many types, as this only holds a single value and can thus enjoy the benefits of remaining strongly typed.
An example use:
public class User extends Entity<User> {
private static final Structure<User> STRUCTURE = Structure.of(User.class, User::new)
.addPrimaryKey("user_id", UUID).property((e) -> e.userID).setDefault(() -> UUID()).build()
.addIndex("username", VCHARS_50).property((e) -> e.username).build()
.addIndex("email", VCHARS_255).property((e) -> e.email).build()
.add("password", VCHARS_255).property((e) -> e.passwordHash).build()
.add("privacy_policy_accepted", EPOCH).property((e) -> e.ppAccepted).setDefault(() -> now()).build()
.add("tos_accepted", EPOCH).property((e) -> e.tosAccepted).setDefault(() -> now()).build()
.add("registration_date", EPOCH).property((e) -> e.registrationDate).setDefault(() -> now()).build()
.buildFor(Schema.MASTER);
public final Property<UUID> userID = new Property<>();
public final Property<String> username = new Property<>();
public final Property<String> email = new Property<>();
public final Property<String> passwordHash = new Property<>();
public final Property<Long> ppAccepted = new Property<>();
public final Property<Long> tosAccepted = new Property<>();
public final Property<Long> registrationDate = new Property<>();
public User() {
super(STRUCTURE);
}
public void hashAndSetPassword(String password) {
this.passwordHash.set(Argon2Factory.create(Argon2Types.ARGON2id).hash(3, 102800, 1, password.toCharArray()));
}
public boolean verifyPassword(String attempt) {
return Argon2Factory.create(Argon2Types.ARGON2id).verify(passwordHash.get(), attempt.toCharArray());
}
}
With each entity property using the following:
public class Property<T> {
private T currentValue;
public void set(T newValue) {
this.currentValue = newValue;
}
public T get() {
return this.currentValue;
}
@Override
public boolean equals(Object o) {
return Objects.equals(currentValue, o);
}
@Override
public int hashCode() {
return Objects.hashCode(currentValue);
}
@Override
public String toString() {
return String.valueOf(currentValue);
}
}
We can extend or modify this Properties class and make it do more useful stuff for us, like have it record an original value, provided on creation (pulled from a database) and allow it to self-report on whether the current value of the property differs from what it was originally. Useful for determining which columns need to be updated in a database.
Most notably, this eliminates the need to create getters and setters for every new property because the Property has that functionality already. Moreover, the getters/setters are able to be overridden per-property if additional logic is needed.
I naturally ended up using this design while aiming for a more broad goal of eliminating the use of reflection/annotation processors and other black magic from my web framework. However, I’m having difficulty finding it on the internet so that I might be able to research its potential deficiencies.