【问题标题】:Instantiating abstract class multiple times with one action用一个动作多次实例化抽象类
【发布时间】:2014-09-03 23:20:26
【问题描述】:

所以我有一个,比如说,Pet 抽象类,以及它的三个具体实现——比如说CatDogBird。正如具体的类所做的那样,这些家伙共享共同的领域,也有独特的领域——例如,他们都有Legs,但只有Birds 有Wings。所以,GSP 不同,更新方法不同等等。

诀窍是我需要能够在单个操作中实例化、验证和持久化不确定数量的实例。一个简单的实现基本上如下:

create.gsp

Cat Hair Color: <g:textField name="catInstance.hairColor"/>
Dog Hair Color: <g:textField name="dogInstance.hairColor"/>
Bird Feather Color: <g:textField name="birdInstance.featherColor"/>

PetCommand.groovy

class PetCommand {

    Cat catInstance
    Dog dogInstance
    Bird birdInstance

}

PetController.groovy

def save(PetCommand cmd) {

    def catInstance = cmd.catInstance
    def dogInstance = cmd.dogInstance
    def birdInstance = cmd.birdInstance

    /* do stuff */

}

当然,在实际应用程序中,这会变得更加混乱,这完全违背了使用抽象类的目的。

有没有什么方法可以一次性绑定多个Pet 实例,然后循环遍历它们,例如,传入参数进行更新?我不知道,这整件事很混乱。

Command 对象并不是绝对必要的,但它们解决了 Grails 控制器的许多烦人的冗余问题。

【问题讨论】:

  • 在这里使用命令对象是正确的方法。没有办法使用 Grails 中的内置绑定将抽象类列表绑定到具体实例。但是,您可以探索使用工厂并使您的 GSP 更通用,例如pet[0].somePropertypet[0].type' and pet[1].someProperty, pet[1].someOtherProperty, pet[0].type'。但是,根据您的域模型的复杂程度,这可能会变得非常难以维护。只是一些需要考虑的事情。
  • 这是一个有趣的想法。您会使用带有工厂的LazyList 来实例化命令对象中的宠物吗?而且我想在 GSP 中,我会遍历控制器提供的数组,并根据...提取模板...
  • 您对使用LazyList 和工厂的命令对象是正确的。我有点假设 GSP 是静态的,但如果你想基于某种类型的配置或元数据来呈现它,我想你可以。真的取决于你的要求。
  • 是的,我的部门永远不可能有简单的要求;)
  • 然后使用某种类型的元数据和工厂应该能够满足您的需求。

标签: grails data-binding abstract-class instantiation command-objects


【解决方案1】:

所以根据上面 Joshua Moore 的 cmets,看起来答案是这样的:

模板(例如,_bird.gsp

    Bird Feather Color: <g:textField name="pets['bird'].featherColor"/>

普惠制

    /* based on other logic, render appropriate templates */

命令对象

    List pets = [].withLazyDefault { petType -> return PetFactory.createPet(petType) }

工厂(简单实现)

    def createPet(String petType) {
        switch (petType) {
            case 'bird': return new Bird(); break;
        // ...etc...
    }

控制器

def update(PetCommand cmd) {
    cmd.pets?.each {
        petService.update(it, params)
    }
    /* ...etc... */
}

服务

def update(Pet petInstance, Map params) {
    petInstance.update(params)
}

def update(Map params) {
    /* domain-specific business logic based on user input */
}

这还没有实现;如果它不起作用,我会尝试更新它。

【讨论】:

  • 仅供参考,它基本上可以工作。命令对象的绑定深度不超过一层,但这可能已通过 2.3 中的新绑定修复。我最终只是在 domain.update() 方法中手动分配未绑定的参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-08
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 1970-01-01
  • 1970-01-01
  • 2015-10-06
相关资源
最近更新 更多