Bloc事件与Clean Architecture用例是否等同?合并方案及合理性探讨
Bloc事件与Clean Architecture用例的合并疑问
代码示例
Clean Architecture用例代码
final class AuthUseCases { final DataProxy dataProxy; const AuthUseCases(this.dataProxy); Future<AuthSession> login(TCredential credential) async { // a lot of lines here... } AuthSession logout(AuthSession session) { // a few lines here... } }
Freezed实现的Bloc事件代码
@freezed sealed class TmdbEvent with _$TmdbEvent { const factory TmdbEvent.login(TCredential credential) = LoginEvent; const factory TmdbEvent.logout() = LogoutEvent; } class TmdbBloc extends Bloc<TmdbEvent, PageState> { // more lines here... }
疑问
我认为Bloc事件与Clean Architecture用例是相同的,因此考虑将这两类合并,现提出以下问题:
- 该观点是否正确?
- 若合并,新类应如何编写?(我刚接触Freezed包)
- 合并为单个类还是分开维护更合适?
解答
1. 观点是否正确?
不完全正确。Bloc事件本质是UI层触发的动作指令,仅负责传递触发操作的必要数据,本身不包含业务逻辑;而Clean Architecture的用例是业务逻辑的封装载体,包含具体的业务规则、数据交互逻辑,属于领域层/业务层的核心组件。
两者只是在命名、触发动作上存在对应关系,但职责边界完全不同:Bloc事件是"告诉Bloc要做什么",用例是"具体怎么做",属于分层架构中不同层级的产物。
2. 若尝试合并,如何编写?
如果硬要合并,核心思路是让Freezed生成的事件类同时承载用例的业务逻辑,但这种写法会打破分层原则,仅做技术演示:
@freezed sealed class AuthEvent with _$AuthEvent { // 注入数据代理,Freezed类通常不建议直接持有依赖,这里是为了合并的妥协 final DataProxy dataProxy; const AuthEvent._(); // 必须定义私有构造函数才能添加自定义方法 const factory AuthEvent.login(TCredential credential, DataProxy dataProxy) = LoginEvent; const factory AuthEvent.logout(AuthSession session, DataProxy dataProxy) = LogoutEvent; // 把原用例的业务逻辑放到事件的方法中 Future<AuthSession> executeLogin() async { if (this is LoginEvent) { final event = this as LoginEvent; // 原login用例的业务逻辑代码 // ... return AuthSession(); } throw StateError("Invalid event type"); } AuthSession executeLogout() { if (this is LogoutEvent) { final event = this as LogoutEvent; // 原logout用例的业务逻辑代码 // ... return event.session; } throw StateError("Invalid event type"); } }
在Bloc中的使用方式:
class AuthBloc extends Bloc<AuthEvent, PageState> { AuthBloc() : super(InitialState()) { on<AuthEvent>((event, emit) async { if (event is LoginEvent) { final session = await event.executeLogin(); emit(LoggedInState(session)); } else if (event is LogoutEvent) { event.executeLogout(); emit(LoggedOutState()); } }); } }
⚠️ 注意:这种写法违背了Clean Architecture的分层思想,把业务逻辑耦合到了UI层的事件类中,后续维护、测试都会变得困难,不推荐在实际项目中使用。
3. 合并还是分开维护?
强烈建议分开维护,原因如下:
- 职责单一:用例专注业务逻辑,可独立测试、复用(比如除了Bloc,其他业务场景也能调用用例);Bloc事件专注传递动作指令,保持轻量。
- 分层清晰:符合Clean Architecture的分层原则,领域层(用例)不依赖UI层(Bloc事件),降低模块间耦合。
- 可扩展性:后续新增业务逻辑只需修改用例,新增UI触发动作只需新增Bloc事件,互不影响。
内容的提问来源于stack exchange,提问作者Ουιλιαμ Αρκευα
相关产品推荐
相关产品推荐

