领域接口化设计
把服务对象(service)和资源库对象(repository)设计成接口是最常见的。但是这对接口化的认识还远远不够,我们需要更深入地去分析接口化设计和更全面地应用接口化编程。所以我们要讨论的是全面接口化,尤其是对领域模型接口化的认识。
领域接口化
通常的情况下我们会把领域模型设计成类(class),但是你有没有想过把领域模型设计成接口(interface)?比如:
public interface User {
// ...
}
public class UserImpl implements User {
// ...
}
这样的设计似乎没有任何价值,那么继续深入地看看。比如:
这时候看起来有点东西,因为我们为了适配不同的数据源,提供了不同的实现类。
最开始要把领域对象设计成接口,确实是为了在不同的 ORM 框架之间实现无缝切换。因为 JPA 对面向对象的支持最好,而 Mybatis 因为简单在大环境下比较流行。在解决这个问题时,通常使用层内包裹或者叫对象转换的方式来解决。具体来说是在持久层使用持久化对象(PO)与领域对象(DO)的之间进行转换。例如:
public class JpaUserRepository implements UserRepository {
// ...
@Override
public Optional<User> findById(String id) {
UserPO userPO = this.entityManager.find(UserPO.class, id);
return Optional.ofNullable(userPO).map(UserPO::toUser);
}
@Override
public User save(User user) {
UserPO userPO = this.entityManager.find(UserPO.class, user.getId());
userPO.setNickname(user.getNickname());
// ...
return this.entityManager.merge(userPO).toUser();
}
}
其中 UserPO 对象基本上是对数据库表的映射,然后将数据与 User 对象进行交换。对于这种需要交换的方式既有性能的损失又比较繁琐,将 User 设计成接口后,这个交换的问题就比较简单地解决了,如下:
public class