设计模式与原则
SOLID、DDD、CQRS 与 TDD。
设计模式与原则
这一课你将能做到
- 面对一段「又臭又长」的代码,用 SOLID 原则准确指出它违反了哪几条,并给出重构方向
- 画出本站课程域的 DDD 限界上下文图,标出聚合根和领域事件
- 解释 CQRS 和最终一致性的适用场景,能画出读写分离的架构图
为什么要学
设计模式和原则不是炫技,是应对变更的武器。需求变了 100 次,你的代码改了 100 次还是改到崩溃——说明设计出了问题。
人话:好的设计像乐高,换一块积木不会散架;坏的设计像俄罗斯方块,塞进去就拔不出来,越堆越高。
面试场景:「你用过哪些设计模式?」「你们系统的分层是怎么设计的?」「订单状态机怎么保证一致性?」——这些问题没有标准答案,但 SOLID 和 DDD 是你的分析框架。
先建立图像
本站课程模块的分层演进:
【贫血模型】(初学者常见)
Controller → Service(全是 if/else 业务逻辑) → DAO → MySQL
【充血模型/DDD】(演进后)
Controller → ApplicationService(编排)
→ DomainService(跨聚合逻辑)
→ CourseAggregate(聚合根,内含业务规则)
→ Repository(接口,由 DAO 实现)
→ MySQL / Redis
跟着做
步骤 1:用 SOLID 审查一段坏代码
// 违反 SRP:一个类干三件事
public class CourseManager {
public void createCourse() { ... } // 业务逻辑
public void sendEmail() { ... } // 通知逻辑
public void generateReport() { ... } // 报表逻辑
}
重构后:
public class CourseService {
private final NotificationService notifier;
private final ReportService reporter;
public void createCourse(CreateCourseCmd cmd) {
// ... 只负责课程创建
notifier.notifyCourseCreated(course); // 委托通知
reporter.trackCreation(course); // 委托报表
}
}
步骤 2:识别 DDD 限界上下文
本站可拆出三个上下文:
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 课程上下文 │────→│ 订单上下文 │←────│ 用户上下文 │
│ │ │ │ │ │
│ 聚合:Course │ │ 聚合:Order │ │ 聚合:User │
│ 事件:Course │ │ 事件:Order │ │ 事件:User │
│ Published │ │ Created │ │ Registered │
└──────────────┘ └──────────────┘ └──────────────┘
上下文映射:
- 课程上下文 → 订单上下文:上游(UL 以课程为准)
- 用户上下文 → 订单上下文:上游
- 订单上下文 → 推荐上下文:领域事件(OrderCreated → 更新推荐模型)
步骤 3:CQRS 推演
本站场景:课程详情页读多写少,且读模型和写模型差异大。
// 写模型(命令端)
public class CourseWriteService {
@Transactional
public void updateCourse(CourseId id, UpdateCmd cmd) {
Course course = courseRepo.findById(id);
course.update(cmd);
courseRepo.save(course);
eventBus.publish(new CourseUpdated(id));
}
}
// 读模型(查询端)
public class CourseReadService {
public CourseDetailDTO getDetail(CourseId id) {
// 直接从 Redis/ES 读,不走领域模型
return cache.getOrLoad(id, () -> elasticSearch.get(id));
}
}