简体   繁体   English

具有单值、强类型属性容器的设计模式的名称是什么?

[英]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.寻找设计模式的名称,通过该名称您可以拥有一个具有公共最终“属性”的 POJO,其中该属性充当某种类型值的持有者/包装器,并包含该值的 getter/setter 以及可能的一些附加值逻辑。

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.我们可以扩展或修改这个 Properties 类,让它为我们做更多有用的事情,比如让它记录一个原始值,在创建时提供(从数据库中提取)并允许它自我报告属性的当前值是否与原来的不同。 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.最值得注意的是,这消除了为每个新属性创建 getter 和 setter 的需要,因为 Property 已经具有该功能。 Moreover, the getters/setters are able to be overridden per-property if additional logic is needed.此外,如果需要额外的逻辑,getter/setter 能够被每个属性覆盖。

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.我自然而然地最终使用了这种设计,同时瞄准了一个更广泛的目标,即从我的 Web 框架中消除使用反射/注释处理器和其他黑魔法。 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.这种包装器“变量”用于诸如 StringProperty 之类的 Observable 属性。 Its primary use is to hold state and have change listeners, binding in general.它的主要用途是保持状态并具有更改侦听器,通常是绑定

It is fruitfully used, like in JavaFX.它得到了卓有成效的使用,就像在 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 .一个我找不到的模式名称,如果将其称为模式,我认为 4 人的帮派会困扰一个,而不是State

Credit to @Michael and @Kayaman for answering in the comments: This is not a known design pattern, contrary to my expectations.感谢@Michael@Kayaman在评论中的回答:这不是一个已知的设计模式,与我的预期相反。

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.换句话说,没有一个人们通常知道的名称来指代我所谓的“属性”,也没有我建议的设计,它假设需要公共 getter 和 setter 并使用公共 final 字段来公开包装器这提供了他们。

This is likely because, as Kayaman pointed out, it's pretty heavy while being not terribly useful.正如 Kayaman 指出的那样,这可能是因为它非常重,但并不是非常有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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