分层架构(Layered Architecture)
什么是分层架构
分层架构(Layered Architecture)是一种将软件系统按照职责划分为多个层次的设计模式。每一层都有明确的职责和边界,上层只能依赖下层,不能反向依赖。这种架构模式通过将系统分解为不同的抽象层次,使得系统更容易理解、开发和维护。
核心思想
分层架构的核心思想是关注点分离(Separation of Concerns)。通过将不同职责的代码分离到不同的层次中,每一层只需要关注自己的职责,不需要了解其他层的实现细节。
主要特点
- 层次分明:每一层都有明确的职责和边界,职责单一
- 单向依赖:上层只能依赖下层,不能反向依赖,形成清晰的依赖关系
- 封装性:每一层都对其上层隐藏实现细节,只暴露必要的接口
- 可替换性:每一层都可以被相同接口的其他实现替换,提高系统的灵活性
- 可测试性:每一层都可以独立测试,便于单元测试和集成测试
典型分层结构
分层架构通常包含以下三个核心层次:
1. 表现层(Presentation Layer / Controller Layer)
职责:
- 接收用户请求(HTTP 请求、RPC 调用等)
- 参数校验和格式化
- 调用业务逻辑层处理请求
- 将业务结果转换为响应格式返回给用户
- 处理异常并返回友好的错误信息
特点:
- 不包含业务逻辑,只负责请求的接收和响应的返回
- 可以支持多种表现方式(Web、移动端 API、RPC 接口等)
- 通常使用 DTO(Data Transfer Object)与业务层交互
常见组件:
- Controller:处理 HTTP 请求
- DTO:数据传输对象,用于层间数据传递
- Validator:参数校验器
- Exception Handler:异常处理器
2. 业务逻辑层(Business Logic Layer / Service Layer)
职责:
- 实现核心业务规则和业务逻辑
- 协调多个数据访问层的操作
- 处理业务异常和业务校验
- 事务管理
- 调用外部服务(如第三方 API、消息队列等)
特点:
- 不依赖具体的数据库实现,只依赖数据访问层的接口
- 包含系统的核心业务逻辑,是最重要的一层
- 可以调用多个 Repository 完成复杂的业务操作
- 通常使用领域模型(Entity/Domain Model)进行业务处理
常见组件:
- Service Interface:服务接口定义
- Service Implementation:服务实现类
- Domain Model:领域模型(业务实体)
- Business Exception:业务异常
3. 数据访问层(Data Access Layer / Repository Layer)
职责:
- 封装数据库操作(增删改查)
- 管理数据库连接和事务
- 提供数据持久化接口
- 处理数据访问异常
特点:
- 隐藏数据库的具体实现细节(SQL、ORM 框架等)
- 为业务层提供统一的数据访问接口
- 可以切换不同的数据库或 ORM 框架而不影响业务层
- 通常使用 Entity 或 DO(Data Object)表示数据库实体
常见组件:
- Repository Interface:数据访问接口
- Repository Implementation:数据访问实现(通常由 ORM 框架自动生成)
- Entity/DO:数据库实体对象
- Mapper:MyBatis 的 Mapper 接口
分层架构的包结构
标准包结构图
com.example.project
│
├── controller # 表现层
│ ├── UserController # 用户控制器
│ ├── OrderController # 订单控制器
│ └── ...
│
├── service # 业务逻辑层
│ ├── UserService # 用户服务接口
│ ├── impl # 服务实现
│ │ ├── UserServiceImpl
│ │ └── OrderServiceImpl
│ └── ...
│
├── repository # 数据访问层
│ ├── UserRepository # 用户数据访问接口
│ ├── OrderRepository # 订单数据访问接口
│ └── ...
│
├── model # 数据模型
│ ├── entity # 实体类(对应数据库表)
│ │ ├── User
│ │ └── Order
│ ├── dto # 数据传输对象
│ │ ├── UserDTO
│ │ └── OrderDTO
│ └── vo # 视图对象
│ └── UserVO
│
├── config # 配置类
│ ├── DatabaseConfig
│ ├── RedisConfig
│ └── ...
│
├── exception # 异常处理
│ ├── BusinessException
│ ├── GlobalExceptionHandler
│ └── ...
│
└── util # 工具类
├── DateUtil
└── ...
详细包结构说明
1. Controller 层(表现层)
controller/
├── UserController.java # 用户相关接口
├── OrderController.java # 订单相关接口
├── ProductController.java # 商品相关接口
└── dto/ # 请求/响应 DTO
├── request/
│ ├── CreateUserRequest.java
│ └── UpdateUserRequest.java
└── response/
├── UserResponse.java
└── ApiResponse.java
职责说明:
- Controller 类负责接收 HTTP 请求,调用 Service 层处理业务
- 使用 DTO 对象进行数据传输,不直接使用 Entity
- 处理参数校验、异常捕获和响应格式化
2. Service 层(业务逻辑层)
service/
├── UserService.java # 用户服务接口
├── OrderService.java # 订单服务接口
├── impl/ # 服务实现
│ ├── UserServiceImpl.java
│ └── OrderServiceImpl.java
└── converter/ # 对象转换器
├── UserConverter.java # Entity 与 DTO 转换
└── OrderConverter.java
职责说明:
- Service 接口定义业务方法
- ServiceImpl 实现具体的业务逻辑
- 可以调用多个 Repository 完成复杂业务
- 使用 Converter 进行 Entity 和 DTO 之间的转换
3. Repository 层(数据访问层)
repository/
├── UserRepository.java # 用户数据访问接口
├── OrderRepository.java # 订单数据访问接口
└── mapper/ # MyBatis Mapper(如果使用)
├── UserMapper.java
└── UserMapper.xml
职责说明:
- Repository 接口定义数据访问方法
- 如果使用 JPA,实现由框架自动生成
- 如果使用 MyBatis,需要编写 Mapper 接口和 XML
4. Model 层(数据模型)
model/
├── entity/ # 实体类(对应数据库表)
│ ├── User.java
│ ├── Order.java
│ └── BaseEntity.java # 基础实体(包含公共字段)
│
├── dto/ # 数据传输对象
│ ├── UserDTO.java
│ ├── OrderDTO.java
│ └── PageDTO.java # 分页对象
│
└── vo/ # 视图对象(用于展示)
├── UserVO.java
└── OrderDetailVO.java
职责说明:
- Entity:对应数据库表,包含 JPA 注解
- DTO:用于层间数据传输,不包含业务逻辑
- VO:用于前端展示,可能包含多个 Entity 的数据
完整项目包结构示例
以下是一个完整的 Spring Boot 项目的包结构:
com.example.ecommerce
│
├── controller/ # 表现层
│ ├── UserController.java
│ ├── OrderController.java
│ ├── ProductController.java
│ └── dto/
│ ├── request/
│ │ ├── CreateUserRequest.java
│ │ ├── UpdateUserRequest.java
│ │ └── QueryUserRequest.java
│ └── response/
│ ├── UserResponse.java
│ ├── ApiResponse.java
│ └── PageResponse.java
│
├── service/ # 业务逻辑层
│ ├── UserService.java
│ ├── OrderService.java
│ ├── ProductService.java
│ ├── impl/
│ │ ├── UserServiceImpl.java
│ │ ├── OrderServiceImpl.java
│ │ └── ProductServiceImpl.java
│ └── converter/
│ ├── UserConverter.java
│ ├── OrderConverter.java
│ └── ProductConverter.java
│
├── repository/ # 数据访问层
│ ├── UserRepository.java
│ ├── OrderRepository.java
│ ├── ProductRepository.java
│ └── mapper/ # MyBatis Mapper
│ ├── UserMapper.java
│ ├── UserMapper.xml
│ └── ...
│
├── model/ # 数据模型
│ ├── entity/
│ │ ├── User.java
│ │ ├── Order.java
│ │ ├── Product.java
│ │ └── BaseEntity.java
│ ├── dto/
│ │ ├── UserDTO.java
│ │ ├── OrderDTO.java
│ │ └── ProductDTO.java
│ └── vo/
│ ├── UserVO.java
│ └── OrderDetailVO.java
│
├── config/ # 配置类
│ ├── DatabaseConfig.java
│ ├── RedisConfig.java
│ ├── SwaggerConfig.java
│ └── WebMvcConfig.java
│
├── exception/ # 异常处理
│ ├── BusinessException.java
│ ├── GlobalExceptionHandler.java
│ └── ErrorCode.java
│
├── util/ # 工具类
│ ├── DateUtil.java
│ ├── StringUtil.java
│ └── JsonUtil.java
│
└── constant/ # 常量类
├── UserConstant.java
└── OrderConstant.java
层间交互流程
请求处理流程
用户请求
↓
Controller 层(接收请求、参数校验)
↓
Service 层(业务逻辑处理)
↓
Repository 层(数据访问)
↓
数据库
↓
Repository 层(返回 Entity)
↓
Service 层(转换为 DTO、处理业务逻辑)
↓
Controller 层(转换为 Response、返回给用户)
↓
用户响应
数据流转
请求阶段:
- Request DTO → Controller → Service → Repository → Entity → 数据库
响应阶段:
- 数据库 → Entity → Repository → Service(转换为 DTO)→ Controller(转换为 Response)→ 用户
依赖关系
Controller 层
↓ 依赖
Service 层
↓ 依赖
Repository 层
↓ 依赖
数据库/ORM 框架
重要原则:
- Controller 只能依赖 Service,不能直接依赖 Repository
- Service 只能依赖 Repository,不能直接访问数据库
- Repository 只负责数据访问,不包含业务逻辑
详细实现示例
完整代码示例
下面通过一个用户管理的完整示例,展示分层架构的实现:
1. Entity(实体类)
// model/entity/User.java
@Entity
@Table(name = "users")
public class User extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50)
private String username;
@Column(nullable = false, unique = true)
private String email;
@Column(nullable = false)
private String password;
@Enumerated(EnumType.STRING)
private UserStatus status;
// getters, setters, constructors
}
2. DTO(数据传输对象)
// model/dto/UserDTO.java
public class UserDTO {
private Long id;
private String username;
private String email;
private UserStatus status;
// getters, setters
}
// controller/dto/request/CreateUserRequest.java
public class CreateUserRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 50, message = "用户名长度必须在3-50之间")
private String username;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@NotBlank(message = "密码不能为空")
@Size(min = 6, message = "密码长度不能少于6位")
private String password;
// getters, setters
}
// controller/dto/response/UserResponse.java
public class UserResponse {
private Long id;
private String username;
private String email;
private UserStatus status;
private LocalDateTime createTime;
// getters, setters
}
3. Repository(数据访问层)
// repository/UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
/**
* 根据邮箱查询用户
*/
Optional<User> findByEmail(String email);
/**
* 根据状态查询用户列表
*/
List<User> findByStatus(UserStatus status);
/**
* 检查邮箱是否存在
*/
boolean existsByEmail(String email);
/**
* 根据用户名和状态查询
*/
Optional<User> findByUsernameAndStatus(String username, UserStatus status);
}
4. Service(业务逻辑层)
// service/UserService.java(接口)
public interface UserService {
/**
* 根据ID查询用户
*/
UserDTO getUserById(Long id);
/**
* 创建用户
*/
UserDTO createUser(CreateUserRequest request);
/**
* 更新用户
*/
UserDTO updateUser(Long id, UpdateUserRequest request);
/**
* 删除用户
*/
void deleteUser(Long id);
/**
* 分页查询用户
*/
PageDTO<UserDTO> getUserList(QueryUserRequest request);
}
// service/impl/UserServiceImpl.java(实现)
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional(readOnly = true)
public UserDTO getUserById(Long id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
return UserConverter.toDTO(user);
}
@Override
public UserDTO createUser(CreateUserRequest request) {
// 1. 业务校验:检查邮箱是否已存在
if (userRepository.existsByEmail(request.getEmail())) {
throw new BusinessException("邮箱已被注册");
}
// 2. 创建用户实体
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPassword(encodePassword(request.getPassword())); // 密码加密
user.setStatus(UserStatus.ACTIVE);
// 3. 保存到数据库
User savedUser = userRepository.save(user);
// 4. 转换为 DTO 返回
return UserConverter.toDTO(savedUser);
}
@Override
public UserDTO updateUser(Long id, UpdateUserRequest request) {
// 1. 查询用户
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
// 2. 更新用户信息
if (request.getUsername() != null) {
user.setUsername(request.getUsername());
}
if (request.getEmail() != null && !user.getEmail().equals(request.getEmail())) {
// 如果邮箱改变,需要检查新邮箱是否已被使用
if (userRepository.existsByEmail(request.getEmail())) {
throw new BusinessException("邮箱已被使用");
}
user.setEmail(request.getEmail());
}
// 3. 保存更新
User updatedUser = userRepository.save(user);
return UserConverter.toDTO(updatedUser);
}
@Override
public void deleteUser(Long id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
userRepository.delete(user);
}
@Override
@Transactional(readOnly = true)
public PageDTO<UserDTO> getUserList(QueryUserRequest request) {
// 构建查询条件
Pageable pageable = PageRequest.of(
request.getPageNum() - 1,
request.getPageSize()
);
// 查询数据
Page<User> userPage = userRepository.findAll(pageable);
// 转换为 DTO
List<UserDTO> userDTOList = userPage.getContent().stream()
.map(UserConverter::toDTO)
.collect(Collectors.toList());
return new PageDTO<>(
userDTOList,
userPage.getTotalElements(),
userPage.getTotalPages()
);
}
private String encodePassword(String password) {
// 密码加密逻辑
return BCrypt.hashpw(password, BCrypt.gensalt());
}
}
// service/converter/UserConverter.java(对象转换器)
@Component
public class UserConverter {
public static UserDTO toDTO(User user) {
if (user == null) {
return null;
}
UserDTO dto = new UserDTO();
dto.setId(user.getId());
dto.setUsername(user.getUsername());
dto.setEmail(user.getEmail());
dto.setStatus(user.getStatus());
return dto;
}
public static User toEntity(UserDTO dto) {
if (dto == null) {
return null;
}
User user = new User();
user.setId(dto.getId());
user.setUsername(dto.getUsername());
user.setEmail(dto.getEmail());
user.setStatus(dto.getStatus());
return user;
}
public static UserResponse toResponse(UserDTO dto) {
if (dto == null) {
return null;
}
UserResponse response = new UserResponse();
response.setId(dto.getId());
response.setUsername(dto.getUsername());
response.setEmail(dto.getEmail());
response.setStatus(dto.getStatus());
return response;
}
}
5. Controller(表现层)
// controller/UserController.java
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
@Autowired
private UserService userService;
/**
* 根据ID查询用户
*/
@GetMapping("/{id}")
public ApiResponse<UserResponse> getUser(@PathVariable Long id) {
UserDTO userDTO = userService.getUserById(id);
UserResponse response = UserConverter.toResponse(userDTO);
return ApiResponse.success(response);
}
/**
* 创建用户
*/
@PostMapping
public ApiResponse<UserResponse> createUser(
@Valid @RequestBody CreateUserRequest request) {
UserDTO userDTO = userService.createUser(request);
UserResponse response = UserConverter.toResponse(userDTO);
return ApiResponse.success(response);
}
/**
* 更新用户
*/
@PutMapping("/{id}")
public ApiResponse<UserResponse> updateUser(
@PathVariable Long id,
@Valid @RequestBody UpdateUserRequest request) {
UserDTO userDTO = userService.updateUser(id, request);
UserResponse response = UserConverter.toResponse(userDTO);
return ApiResponse.success(response);
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public ApiResponse<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ApiResponse.success(null);
}
/**
* 分页查询用户列表
*/
@GetMapping
public ApiResponse<PageResponse<UserResponse>> getUserList(
@Valid QueryUserRequest request) {
PageDTO<UserDTO> pageDTO = userService.getUserList(request);
List<UserResponse> responseList = pageDTO.getList().stream()
.map(UserConverter::toResponse)
.collect(Collectors.toList());
PageResponse<UserResponse> pageResponse = new PageResponse<>(
responseList,
pageDTO.getTotal(),
pageDTO.getTotalPages()
);
return ApiResponse.success(pageResponse);
}
}
// controller/dto/response/ApiResponse.java(统一响应格式)
public class ApiResponse<T> {
private boolean success;
private T data;
private String message;
private Long timestamp;
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.setSuccess(true);
response.setData(data);
response.setMessage("操作成功");
response.setTimestamp(System.currentTimeMillis());
return response;
}
public static <T> ApiResponse<T> error(String message) {
ApiResponse<T> response = new ApiResponse<>();
response.setSuccess(false);
response.setMessage(message);
response.setTimestamp(System.currentTimeMillis());
return response;
}
// getters, setters
}
6. 异常处理
// exception/BusinessException.java
public class BusinessException extends RuntimeException {
private String code;
private String message;
public BusinessException(String message) {
super(message);
this.message = message;
this.code = "BUSINESS_ERROR";
}
}
// exception/GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ApiResponse<Void>> handleBusinessException(
BusinessException ex) {
ApiResponse<Void> response = ApiResponse.error(ex.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
/**
* 处理参数校验异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiResponse<Void>> handleValidationException(
MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", "));
ApiResponse<Void> response = ApiResponse.error(message);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
/**
* 处理其他异常
*/
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<Void>> handleException(Exception ex) {
ApiResponse<Void> response = ApiResponse.error("系统异常,请稍后重试");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
分层架构的优缺点
优点
- 职责清晰:每一层都有明确的职责,代码组织清晰
- 易于理解:新成员可以快速理解代码结构
- 易于维护:修改某一层不会影响其他层
- 易于测试:每一层都可以独立测试
- 可扩展性好:可以轻松添加新的功能模块
- 技术栈解耦:可以替换某一层的技术实现而不影响其他层
缺点
- 性能开销:层间调用可能带来一定的性能开销
- 代码冗余:需要在不同层之间进行对象转换,可能产生冗余代码
- 过度设计:对于简单项目,可能显得过于复杂
- 层间耦合:如果设计不当,可能出现层间耦合问题
适用场景
适合使用分层架构的场景:
- 企业级应用开发
- 需要长期维护的项目
- 团队协作开发
- 需要支持多种前端(Web、移动端、API)
- 业务逻辑复杂,需要清晰的代码组织
不适合使用分层架构的场景:
- 简单的 CRUD 应用(可能过度设计)
- 高性能要求的系统(层间调用有开销)
- 微服务架构中的小服务(可能过于复杂)
包结构可视化图
Mermaid 包结构图
依赖关系图
数据流转图
最佳实践
1. 使用接口定义服务层
原因:便于测试和替换实现
// ✅ 好的做法:使用接口
public interface UserService {
UserDTO getUserById(Long id);
}
@Service
public class UserServiceImpl implements UserService {
// 实现
}
// ❌ 不好的做法:直接使用实现类
@Service
public class UserService {
// 实现
}
2. 使用 DTO 进行层间数据传输
原因:避免暴露 Entity 的内部结构,提高灵活性
// ✅ 好的做法:使用 DTO
public UserDTO getUserById(Long id) {
User user = repository.findById(id);
return UserConverter.toDTO(user); // Entity 转 DTO
}
// ❌ 不好的做法:直接返回 Entity
public User getUserById(Long id) {
return repository.findById(id); // 暴露了 Entity 结构
}
3. 在 Service 层管理事务
原因:业务逻辑的完整性需要事务保证
// ✅ 好的做法:在 Service 层使用 @Transactional
@Service
public class OrderServiceImpl implements OrderService {
@Transactional
public OrderDTO createOrder(CreateOrderRequest request) {
// 多个数据库操作,需要事务保证
orderRepository.save(order);
inventoryRepository.updateStock(productId, quantity);
return OrderConverter.toDTO(order);
}
}
4. 统一异常处理
原因:提供统一的错误响应格式
// ✅ 好的做法:使用全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ApiResponse<Void>> handleBusinessException(
BusinessException ex) {
return ResponseEntity.badRequest()
.body(ApiResponse.error(ex.getMessage()));
}
}
5. 使用 Converter 进行对象转换
原因:集中管理转换逻辑,便于维护
// ✅ 好的做法:使用 Converter
@Component
public class UserConverter {
public static UserDTO toDTO(User user) {
// 转换逻辑
}
}
// ❌ 不好的做法:在 Service 中直接转换
@Service
public class UserServiceImpl {
public UserDTO getUserById(Long id) {
User user = repository.findById(id);
// 直接在这里转换,逻辑分散
UserDTO dto = new UserDTO();
dto.setId(user.getId());
// ...
}
}
6. 参数校验放在 Controller 层
原因:尽早发现参数错误,减少无效请求
// ✅ 好的做法:在 Controller 层使用 @Valid
@PostMapping
public ApiResponse<UserResponse> createUser(
@Valid @RequestBody CreateUserRequest request) {
// 参数校验通过后才会执行
return userService.createUser(request);
}
// CreateUserRequest.java
public class CreateUserRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
}
7. 避免在 Controller 中写业务逻辑
原因:保持 Controller 层的简洁,业务逻辑应该在 Service 层
// ✅ 好的做法:Controller 只负责接收和返回
@PostMapping
public ApiResponse<UserResponse> createUser(
@Valid @RequestBody CreateUserRequest request) {
UserDTO userDTO = userService.createUser(request);
return ApiResponse.success(UserConverter.toResponse(userDTO));
}
// ❌ 不好的做法:在 Controller 中写业务逻辑
@PostMapping
public ApiResponse<UserResponse> createUser(
@Valid @RequestBody CreateUserRequest request) {
// 业务逻辑不应该在这里
if (userRepository.existsByEmail(request.getEmail())) {
throw new BusinessException("邮箱已存在");
}
// ...
}
常见问题和解决方案
问题1:层间循环依赖
问题:Service A 依赖 Service B,Service B 又依赖 Service A
解决方案:
- 提取公共逻辑到新的 Service
- 使用事件驱动模式解耦
- 重新设计业务边界
问题2:DTO 转换代码冗余
问题:每个 Service 方法都需要写转换代码
解决方案:
- 使用 MapStruct 等工具自动生成转换代码
- 使用 Converter 类集中管理转换逻辑
- 使用 Builder 模式简化对象创建
问题3:Service 层过于臃肿
问题:一个 Service 类包含太多方法,职责不清
解决方案:
- 按业务领域拆分 Service
- 使用领域服务(Domain Service)处理复杂业务逻辑
- 提取公共逻辑到工具类或 Helper 类
问题4:跨层调用
问题:Controller 直接调用 Repository
解决方案:
- 严格遵循分层原则,上层只能调用下层
- 使用代码审查和静态分析工具检查
- 在 Service 层提供必要的接口
总结
分层架构是一种经典且实用的软件架构模式,它通过清晰的层次划分和职责分配,帮助开发团队更好地组织和管理代码。
核心要点
- 职责分离:每一层只负责自己的职责
- 单向依赖:上层依赖下层,不能反向依赖
- 接口抽象:使用接口定义服务,提高灵活性
- 数据转换:使用 DTO 进行层间数据传输
- 统一规范:统一的异常处理、响应格式等
适用场景
虽然分层架构可能不是所有场景的最佳选择,但在以下场景中,它仍然是一个可靠的选择:
- 企业级应用开发:需要长期维护和扩展
- 团队协作开发:需要清晰的代码组织规范
- 多端支持:需要支持 Web、移动端、API 等多种前端
- 复杂业务逻辑:需要清晰的业务逻辑组织
学习建议
- 从简单开始:先实现基本的 CRUD 功能,理解各层职责
- 逐步完善:添加异常处理、参数校验、对象转换等
- 实践优化:在实际项目中应用,不断优化和改进
- 学习其他架构:了解六边形架构、洋葱架构等,对比学习
通过掌握分层架构,你可以更好地组织代码,提高代码质量和可维护性,为后续学习更复杂的架构模式打下基础。
