zoukankan      html  css  js  c++  java
  • 利用Apache Isis快速原型化-宠物诊所的宠物管理

    前言

    Apache Isis是DDD方法的一个实现框架。

    需求分析

    宠物诊所需要记录宠物的资料,包括类型、名字、及其主人。

    多个宠物可能同属于一个主人。

    宠物可能更换主人。

    宠物主人记录姓名,我们可以按姓名来查找宠物主人。

    需求建模

    根据需求,我们可以创建宠物(Pet)和宠物主人(Owner)两个实体类。宠物和主人是一对多的关系。宠物可以变更主人,当然这里我仅限于宠物来选择主人,那给宠物换主人就是宠物自身的一个行为。

    创建宠物和创建宠物主人,我们需要相应业务对象来进行初始化操作。这个业务对象可以认为是一个工厂,专门用来创建不存在的实体对象。

    宠物主人的查询,我们也是通过业务对象来进行实体的检索。这个业务对象可认为是一个实体仓库,我们从中检索需要的实体对象。

    通过以上描述,我们建立以下的UML图形。

    宠物诊所静态模型

    注:由于业务规则相当简单,为了简化编程步骤,这里的宠物主人的查询和创建放到了一个类中。

    程序设计

    ISIS的程序设计,关注点是业务规则(Service、Action、Entity)。Service为功能项,表现为主菜单;Action为用户操作,表现为菜单项或按钮;Entity用户操作的内容或结果,表现为具体的数据表单。Service和Entity都可以承载Action。

    宠物主人管理的业务实现

    将宠物主人的业务对象定义为DomainService,表明此对象宠物主人操作的入口。DomainService.repositoryFor()表明,这个类也是Owner的实体仓库。Owners 在系统中对应一个菜单。

    @DomainService(repositoryFor = Owner.class)public class Owners {
    //....
    }

    给这个类创建两个动作(方法),一个是创建宠物主人(Owner),另一个是用名字来查询。create方法对应创建这个动作,在界面上对应一个Create的菜单项。create参数对应创建动作要输入的内容,在界面上表现为一个输入表单。findByName同理,不过create和findByName的区别是返回不一样,前者返回所创建实体的内容(详情页),后者返回查询的实体集合(列表页)。

     @MemberOrder(sequence = "2")
        public Owner create(
                final @ParameterLayout(named = "Name") String name) {
            final Owner obj = repository.instantiate(Owner.class);
            obj.setName(name);
            repository.persist(obj);
            return obj;
        }
    
        //endregion
    
        //region > findByName (action)
        @MemberOrder(sequence = "1")
        public List<Owner> findByName(
                @ParameterLayout(named = "Name")
                final String name) {
            final String nameArg = String.format(".*%s.*", name);
            final List<Owner> owners = repository.allMatches(
                    new QueryDefault<>(
                            Owner.class,
                            "findByName",
                            "name", nameArg));
            return owners;
        }

    这里使用了持久化服务,这里的持久化是保用的关系型数据库。

    宠物管理的业务实现

    同样先定义Service。

    @DomainService(repositoryFor = Pet.class)
    public class Pets {
    //...
    }

    再创建Action

    public Pet create(
                final @ParameterLayout(named = "宠物名字") String name,
                final @ParameterLayout(named = "宠物类型") PetSpecies species,@ParameterLayout(named = "宠物主人") final Owner owner) {
            final Pet pet = repository.instantiate(Pet.class);
            pet.setName(name);
            pet.setSpecies(species);
            pet.setOwner(owner);
            repository.persist(pet);
            return pet;
        }

    Pet的Action

        public Pet changeOwner(Owner owner) {
            setOwner(owner);
            return this;
        }

    一些扩展设计

    对于宠物主人的选择,为了达到与相应实体类的完全匹配,更多的时候考虑采用下拉选择。ISIS提供了一些协定,比如choice,autoComplete前辍的动作,辅助数据项的选择。

        public List<Owner> autoComplete0ChangeOwner(final @MinLength(1) String name) {
            return owners.findByName(name);
        }

      

    public List<Owner> autoCompleteOwner(final @MinLength(1) String name) {
    return owners.findByName(name);
    }

     
    autoComplete0ChangeOwner 方法可以理解为:autoComplete模糊,对应的参数位置: 0 ,对应的动作:ChangeOwner,
    autoCompleteOwner,对应属性修改的自动完成。

    运行效果

    创建宠物实体

    宠物列表

    宠物详情

    修改宠物主人

  • 相关阅读:
    标准C++中的string类的用法总结
    JSON用法简介
    拷贝构造函数的调用时机
    define中的:#,##,#@
    一个二维码支持支付宝和微信支付(下)
    一个二维码支持支付宝和微信支付(上)
    【JAVA笔记】JAVA后端实现统一扫码支付:微信篇
    java生成二维码,读取(解析)二维码图片
    Java程序员的日常—— IOUtils总结
    Java: Map里面的键和值可以为空吗?
  • 原文地址:https://www.cnblogs.com/icoolno1/p/7250935.html
Copyright © 2011-2022 走看看