短知识:丰富你的领域(实体)对象

该文章主要介绍自己根据对领域驱动设计的理解结合开发实际而赋予领域对象更多的实际行为,而不仅仅是作为一个简单的数据载体而存在。

DO(Domain Object)优化

在贫血模型里,领域对象一般只作为数据载体而存在,只有get和set方法,这也导致一些简单的业务逻辑重复出现在多个地方,如仅把对象里的值提出来去处理判断,但这些行为放到对象中可以更加丰富DO的行为,增加代码可读性,下面以一个优化对象作为数据载体与赋予简单逻辑后的操作对比为例。

  • 作为数据载体的领域对象
@Data
@Accessors(chain = true)
public class Discount {
 private Long id;
 /**
 * 状态(0-禁用,1-可用,2-过期) {@link DiscountConstant.Status}
 */
 private Integer status;
 /**
 * 类型(1-折扣,2-优惠券) {@link DiscountConstant.Type}
 */
 private Integer type;
 /**
 * 折扣/优惠券价
 */
 private Integer value;
}

当需要进行一些逻辑处理,如返回优惠信息,判断状态等,可能就会在多处出现以下的代码块:

if(Objects.equals(discount.getStatus(),status){
  // do something
}

String discountMsg = DiscountConstant.Type.DISCOUNT.equals(discount.getType()) ? discount.getValue() + "折" : "优惠券" + discount.getValue() + "元";
  • 赋予逻辑的领域对象
@Data
@Accessors(chain = true)
public class Discount {
    private Long id;
    /**
     * 状态(0-禁用,1-可用,2-过期) {@link DiscountConstant.Status}
     */
    private Integer status;
    /**
     * 类型(1-折扣,2-优惠券) {@link DiscountConstant.Type}
     */
    private Integer type;
    /**
     * 折扣/优惠券价
     */
    private Integer value;

    /**
     * {@link DiscountConstant.Status}
     */
    public boolean isStatusEqual(Integer status) {
        return Objects.equals(this.status, status);
    }

    /**
     * {@link DiscountConstant.Type}
     */
    public boolean isTypeEquals(Integer type) {
        return Objects.equals(this.type, type);
    }

    /**
     * {@link DiscountConstant.Type}
     */
    public String getDiscountMsg() {
        return DiscountConstant.Type.DISCOUNT.equals(this.type) ? value + "折" : "优惠券" + value + "元";
    }
}

当要获取优惠信息时,如果返回页面的是Discount这个对象时,则无需任何处理了,getDiscountMsg方法会返回discountMsg信息;当作为逻辑处理获取信息时,也可以调用discountMsg而无需重复写类型判断与字符串拼接。进行状态判断时,使用领域对象里的方法进行判断更具有可读性:

if(discount.isStatusEquals(status)){
 // do something
}

VO(Value Object)优化

值对象在Web应用层中一般表示为表现层(前端)的对象,与DDD中的值对象有所不同。前端进行VO传参时,VO也可进行类似DO的优化,如复杂参数的校验,对象的转换,对象转换例子:

@Data
public class UserVO {
    @NotBlank
    private String id;
    @NotBlank
    private String username;
    @NotBlank
    private String password;
    @Range(min = 1, max = 3)
    private Integer status;

    public UserBase userBase(){
        UserBase userBase = new UserBase();
        BeanUtils.copyProperties(this,userBase);
        return userBase
    }
}

引申领域模型

  • 贫血模型:领域对象(DO)里没有业务逻辑,只含简单而的数据操作方法(如get、set、toString),从业务层面上看仅仅是一个数据载体在业务与存储介质之间进行传输的数据载体。
  • 充血模型:领域对象里拥有自己的状态与行为,大多业务逻辑和持久化放在DO里,业务逻辑层只是简单封装部分业务逻辑以及控制事务等。

贫血模型与充血模型应用分层差别不大,主要区别在于逻辑的处理,如下图(左图参考自《领域驱动设计:软件核心复杂性应对之道》,右图参考自《阿里巴巴Java开发手册》):
在这里插入图片描述

结合实际

充血模型对开发人员的业务了解要求较高,需要开发人员清楚的认知业务划分,什么需要放到service层,什么需要放到DO层,且DO中还包含DAO进行数据持久化(依赖倒置原则),这对开发人员来说十分混乱。但在实际开发中,并不一定必须按照死规则去编写代码,可以借鉴充血模型的逻辑处理,灵活开发,为贫血模型中的领域对象赋予数据对象一定的逻辑,提高代码的复用性、可读性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值