CompoundPropertyModel中对象的重写getter方法

姆万特罗巴

这是一个在Wicket中使用CompoundPropertyModel时经常遇到的问题的简单示例:

这是我的实体Item及其模型ItemModel和控制器ItemController

public class Item implements Serializable {

    private static final long serialVersionUID = 1L;
    private long createdTimestamp;

    public Item(long createdTimestamp) {
        super();
        this.createdTimestamp = createdTimestamp;
    }

    public long getCreatedTimestamp() {
        return createdTimestamp;
    }

    public void setCreatedTimestamp(long createdTimestamp) {
        this.createdTimestamp = createdTimestamp;
    }
}

public class ItemModel extends CompoundPropertyModel<Item> {

    private static final long serialVersionUID = 1L;

    public ItemModel(Item object) {
        super(object);
    }
}

public class ItemController {

    public static int getDuration(Item item) {
        return Days.daysBetween(new DateTime(item.getCreatedTimestamp()), new DateTime()).getDays();
    }
}

假设我要在面板上显示createdTimestamp持续时间如果我做这样的事情:

public class ItemPanel extends GenericPanel<Item> {

    private static final long serialVersionUID = 1L;

    public ItemPanel(String id, ItemModel itemModel) {
        super(id);
        setModel(itemModel);
        add(new Label("createdTimestamp"));
        add(new Label("duration"));
    }
}

标签createdTimestamp将被显示为一个长值,因为那是getCreatedTimestamp()方法返回的结果,面板会抛出异常,因为在class中没有实现getDuration()方法Item

一种可能的解决方案是为该类创建一个包装器,该包装器Item可以称为ItemView

public class ItemView implements Serializable {

    private static final long serialVersionUID = 1L;
    private Item item;

    public ItemView(Item item) {
        super();
        this.item = item;
    }

    public Date getCreatedTimestamp() {
        return new Date(item.getCreatedTimestamp());
    }

    public int duration() {
        return ItemController.getDuration(item);
    }
}

它将起作用,但是我不喜欢这种解决方案,因为如果您有很多实体并且它们具有许多字段,则为所有实体创建和使用包装器类可能会非常耗时。

Item已经有包装器,称为ItemModel这就是为什么我想在此类中创建getter方法并强制模型使用它们。

这是我的意思的示例:

public class ItemModel extends CompoundPropertyModel<Item> {

    private static final long serialVersionUID = 1L;

    public ItemModel(Item object) {
        super(object);
    }

    public Date getCreatedTimestamp() {
        return new Date(getObject().getCreatedTimestamp());
    }

    public int duration() {
        return ItemController.getDuration(getObject());
    }
}

但是在这种情况下,模型将忽略getter方法。到目前为止,我还没有找到如何强制模型使用它们的方法。有什么办法吗?

斯文迈尔

当您在组件和属性之间进行直接映射时,CompoundPropertyModel非常有用。但是有时使用AROM会更容易:

add(new Label("createdTimestamp", new AbstractReadOnlyModel<Date>() {
  public Date getObject() {
    return new Date(getModelObject().getCreatedTimestamp());
  }
});

请注意,使用Wicket 8,您可以编写得更短:

add(new Label("createdTimestamp", () -> new Date(getModelObject().getCreatedTimestamp())));

(由于实际上我们只是从Long转换为Date,所以最好使用转换器。)

Item已经有包装器,称为ItemModel。这就是为什么我想在此类中创建getter方法并强制模型使用它们

除了IModel中定义的方法外,模型永远不能有其他方法-Wicket不会调用其中添加的任何方法,但最终会导致组件之间不必要的依赖关系(例如,面板需要使用ItemModel作为参数)。

为所有实体创建和使用包装器类非常耗时

我想知道为什么要定义ItemModel。最好只接受构造函数中的任何模型:

public ItemPanel(String id, IModel<Item> itemModel) {
    super(id, new CompoundPropertyModel<Item>(itemModel);
}

为什么调用者应该知道您的面板内部使用了CompositePropertyModel?

追问:
正当理由,以创建自己的模型实现。看看随Wicket一起带来的那些:

  • AbstractReadOnlyModel
  • LoadableDetachableModel
  • 资源模型
  • StringResourceModel
  • ListItemModel
  • 属性模型
  • 复合属性模型
  • 反馈消息模型
  • Lambda模型
  • ...

它们都有存在的技术原因。您将根据自己的技术要求创建自己的模型实现,例如

new EntityModel(uuid, clazz)
new PropertyInYourGeneratedLegacyObjectModel(order, R.id.ORDER_NUMBER)

我看过其他一些我怀疑的模型实现。以下两种方法通常具有其他方法,可能会发出某种错误的气味:

new TransactionalModel(wrapped).commit()
new AsyncModel(wrapped).startAsync()

人们提倡创建与您的域相关的可重用模型-例如OrderSumModel-但是恕我直言,这失败了。领域逻辑迟早会包含在模型中,您会看到以下模式出现:

BigDecimal sum = new OrderSumModel(order).getObject();

大多数时候,当我需要一些特殊的东西时,我只是在写匿名内部类:

new Label("sum", new AbstractReadOnlyModel() {
  public BigDecimal getObject() {
    return service.calculateSum(getModelObject());
  }
});

如上所述,使用Java 8和Wicket 8,这变得更加容易编写:

new Label("sum", () -> service.calculateSum(getModelObject()));

与往常一样,有例外:
当我需要具有复杂域逻辑的模型(例如OrderSumModel)时,会将其保留为嵌套的内部类。只要我从多个位置需要它,我就会再考虑一次。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章