领域模型

领域模型与数据模型

  1. Data Modeling:通过数据抽取系统关系,即数据库设计。

通常是先根据业务设计出数据库表结构,后续的所有操作依赖于表,俗称的CRUD工程师。

  1. Object Modeling:通过面向对象抽取系统关系。

Data Modeling

传统mvc分层架构。数据库设计是根本,后续的开发围绕着此展开。

在manager层或者service层,我们封装大多数的功能。并且业务逻辑层承担着所有的业务操作工厂,也会变的很重。

案例:小明买苹果。

public class User{
  private String name;
  private Integer uid;
}

public class Fruit{
  private String name;
  private Integer fruitId;
}

这样会分别有一个小明的User对象和苹果的Fruit对象,在执行买动作的时候,会发生什么?

public class BuyService{
  
  public void buy(User user,Fruit fruit){
    user.addFruit(user);
    fruit.decrease(fruit);
  }
}

就是会显得小明没有任何能力,买个水果都要manager帮忙。

domain Modeling

面向对象设计和面向表设计的不同在于,class有其自身的特性是table所没有的:

  1. 引用

    table之间的引用通常是建立第三张表来维护,复杂且业务同学也很难看懂。

  2. 封装

    class可以有方法,但是table无法完整的表达领域模型,数据表无法感知行为,数据表只知道一个女人的三维,但却不知道这个女人其实还是可以跑的。

  3. 继承,多态

    数据表无法感知行为外,还无法感知行为的区别。一个人可以跑,一个猪也可以跑,但是数据表是无法知道,人跑起来和猪跑起来其实是不一样的。

同样的还是小明买苹果的案例:

public class User(){
  
  private String name;
  private Integer uid;
  
  public void buy(Fruit fruit){
    this.addFruit();
    fruit.decrease();
  } 
}

这样小明本身就具有了买苹果的能力,不需要别人帮忙了。

这样在我们的面向对象的世界里,就有了很多生动形象的领域模型了。service层也变成了基于这些模型所做的操作,但是一些动作也交给了domian objects来完成,相应也会变的很薄。

领域模型并不完成业务,每个domain object都是完成自己应有的行为(signal responsibility)。就比如小明是买苹果还是买香蕉,这些都可以在领域服务里面选择。

这里没有将repostory进行关联,后续会涉及到领域模型的三种模式。

在完成了数据模型设计到领域模型设计的转变后,作者强调的一点是操作是基于领域的,但是复杂的查询还是基于数据库的。所有复杂的查询还是要绕过domain直接和数据库打交道。

即:领域操作->objects,数据查询->tables

领域模型

失血模型

特点:纯内存

基于数据库设计的方式是常见的失血模式,一个class里面除了基本属性外,基本的都是get,set方法。对象之间的关系和操作都隐藏在service里面,比如上面案例,小明并不知道和水果有关系,由manager来维护关系。

贫血模型

特点:纯内存

小明知道了自己有个苹果,苹果也划分出来是属于小明所有。

public class User{
  private Fruit fruit;
  public Fruit getFruit(){return fruit}
}

public class Fruit{
	private User user;
  public User getUser(){return user}
}

这样小明知道了自己还有个苹果。

充血模型

特点:非纯内存

充血模型让对象不在只是单纯的属性说明,而是具有了丰富的行为。不过这种方式也让实体中增加了对数据库的操作,有利有弊。

@Component
public class UserFactory{
    private FruitRepository fruitRepo;
    @Autowired
    public UserFactory(FruitRepository fruitRepo){}
    public User createUser(){
        return new User(fruitRepo);
    }
}

public class User {
  private Fruit fruitRepo;
  public User(Fruit fruitRepo){fruitRepo = this.fruitRepo}
  public Fruit getFruit(){
    return fruitRepo.getById(this.id);
  }
}

贫血模型和充血模型一直存在着讨论。

领域对象

实体

实体是一种带有唯一标志的对象。通常实体也具有完整的生命周期:创建,操作,持久化,销毁。

值对象

值对象通常是一种描述或者一种度量,具有不变性的一种领域对象。

聚合根

是同一个业务的领域对象的聚合,每个聚合里面有一个聚合根。聚合根直接使用唯一标志做关联。每一组聚合都应用单独的模块区分开。

xx.com.ordercontext.domaim.orderaggr
xx.com.ordercontext.domaim.taskaggr

Last updated

Was this helpful?