一文讲透 DTO / DAO / VO / Entity
·
——从 Java 到 Flutter 的统一架构认知
在做 Java 后端、Flutter、甚至前端工程时,你一定见过这些名词:
-
DTO
-
DAO
-
VO
-
Entity
-
Repository
但很多人是:
“听过、用过、但说不清楚区别”
这篇文章,我从 工程实践 + 架构设计 的角度,帮你一次性理清这些概念,并给出一套真正能落地的结构模型。
一、先给结论
只记住这 5 句话就够了:
DTO 是数据长什么样
DAO 是数据从哪来
Repository 是业务入口
Entity 是业务实体
VO 是业务中的“值”
二、整体架构图(核心)
下面这张图,是整篇文章的核心 👇
你可以把它当成「后端 / Flutter / Clean Architecture 通用模型」。
✅ 架构图(通用版)
┌──────────────┐
│ UI / 页面 │
└───────┬──────┘
│
v
┌─────────────────────────────┐
│ ViewModel / Controller / Bloc│
└───────────┬─────────────────┘
│
v
┌─────────────────────────────┐
│ Repository(业务入口 / 门面) │
└───────┬───────────┬─────────┘
│ │
│ │
v v
┌──────────────┐ ┌──────────────┐
│ DAO(Remote) │ │ DAO(Local) │
│ 接口 / HTTP │ │ DB / 缓存 │
└───────┬──────┘ └───────┬──────┘
│ │
v v
┌─────────┐ ┌─────────┐
│ DTO │ │ DTO │
│ JSON模型 │ │ 本地模型 │
└────┬────┘ └────┬────┘
│ │
└──────┬──────────┘
v
┌──────────────┐
│ Mapper │
│ DTO → Domain │
└──────┬───────┘
v
┌─────────────────────┐
│ Domain(业务模型层) │
├───────────┬─────────┤
│ Entity │ VO │
│ 有ID │ 无ID │
└───────────┴─────────┘
三、DTO:数据传输对象(Data Transfer Object)
✅ 定义
DTO 是 专门用于数据传输的对象,通常直接对应接口返回结构。
特点
-
只负责装数据
-
字段名跟接口一致
-
可以为 null
-
不包含业务逻辑
-
生命周期短
Java 示例
public class UserDTO {
private String userName;
private String avatar;
}
Flutter 示例
@freezed
class UserDto with _$UserDto {
const factory UserDto({
String? userName,
String? avatar,
}) = _UserDto;
factory UserDto.fromJson(Map<String, dynamic> json)
=> _$UserDtoFromJson(json);
}
DTO 就是一个数据容器,用来接收或传递数据,本身不承载业务含义。
四、DAO:数据访问对象(Data Access Object)
✅ 定义
DAO 负责 从哪拿数据
可能是:
-
HTTP 接口
-
数据库
-
本地缓存
-
文件系统
Java 示例
public interface UserDao {
UserDTO getUser();
}
Flutter 示例
class UserRemoteDataSource {
Future<UserDto> getUser() async {
final res = await dio.get('/user');
return UserDto.fromJson(res.data);
}
}
DAO 的特点:
- 不关心业务
- 不做转换
- 只负责“拿数据”
五、Repository:整个架构的核心
✅ 定义
Repository 是 业务访问的统一入口
它负责:
- 决定用远程还是本地数据
- 调用 DAO
- DTO → Domain 转换
- 向上层隐藏数据来源
示例
class UserRepository {
final UserRemoteDataSource remote;
Future<User> getUser() async {
final dto = await remote.getUser();
return dto.toDomain();
}
}
Repository 是:
架构中最重要的一层,没有之一
六、Entity:业务实体(有身份)
定义
Entity 是 有身份、有生命周期的业务对象
class User {
final String id;
final String name;
}
特点:
- 有 ID
- 可以变化
- 代表“某一个具体对象”
七、VO:值对象(最容易被误解)
正确含义(DDD)
VO(Value Object)是没有 ID、只看值是否相等的对象
特点
- 不可变
- 无 ID
- 有业务语义
- 可复用
示例
@freezed
class Email with _$Email {
const factory Email(String value) = _Email;
factory Email.parse(String input) {
if (!input.contains('@')) {
throw Exception('Invalid email');
}
return Email(input);
}
}
VO 是“业务里的名词”,不是数据结构。
八、为什么 Java 项目里也有 VO 文件夹?
因为很多 Java 项目里的 VO,其实是:
👉 View Object(返回给前端的对象)
public class UserVO {
private String name;
private String avatar;
private String vipText;
}
这种 VO 的本质是:
✅ 返回模型
❌ 不是 DDD 的 Value Object
九、两种 VO 的最终区分
| 类型 | 含义 | 是否业务模型 |
|---|---|---|
| VO(Java 常见) | View Object | ❌ |
| VO(DDD) | Value Object |
✅ |
十、最终总结(背)
DTO:数据怎么传
DAO:数据从哪来
Repository:业务入口
Entity:业务对象
VO:业务中的值
更多推荐



所有评论(0)