简体   繁体   中英

What is the name of the design pattern where you have a single-value, strongly typed property container?

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.

This kind of wrapper "variable" is used for Observable properties like StringProperty and such. Its primary use is to hold state and have change listeners, binding in general.

It is fruitfully used, like in JavaFX. And as you mentioned, in entity frameworks. But it definitely is stateful, non-functional, mutable.

A pattern name I cannot find, and I think the gang of 4 would haunt one, if calling this a pattern, other than State .

Credit to @Michael and @Kayaman for answering in the comments: This is not a known design pattern, contrary to my expectations.

In other words, there is not a name by which people generally know to refer to what I'm calling a "Property" nor the design I'm suggesting which assumes public getters and setters are desired and uses public final fields to expose a wrapper which provides them.

This is likely because, as Kayaman pointed out, it's pretty heavy while being not terribly useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM