如何在无法继承扩展类的前提下优雅抽取Bloc文件中的函数逻辑
针对Bloc逻辑拆分的优雅实现方案
Dart语言本身提供了多个原生特性可以解决这个问题,既可以避免工具类的冗余调用,也不会破坏Bloc本身的继承结构:
方案1:使用Mixin注入逻辑(最推荐,调用体验和内置方法完全一致)
Dart的Mixin支持在不修改继承链的前提下,给类注入成员方法,还可以直接访问Bloc内部的公开/同文件私有属性,和直接写在Bloc类里的使用体验没有任何区别:
// 可以拆分到单独的文件中,比如my_bloc_logic.dart mixin MyBlocLogicMixin on Bloc<MyEvent, MyState> { Stream<LogicChainState> mapLoadRequestedToState() async* { final dataRaw = loadData(); final dataProc = initData(dataRaw); yield doSomeMore(dataProc); } MyData initData(MyData dataRaw) { // 逻辑实现 } MyData doSomeMore(MyData dataProc) { // 逻辑实现 } } // 原Bloc类只要引入mixin即可 class MyBloc extends Bloc<MyEvent, MyState> with MyBlocLogicMixin { @override Stream<MyState> mapEventToState(MyEvent event) async* { yield* event.map( loadRequested: (e) => mapLoadRequestedToState(), dataEntered: (e) => _mapDataEnteredToState(), ); } // 其他原有逻辑 }
如果需要拆分私有方法,只要把mixin和Bloc类放在同一个文件下,方法名加下划线即可实现私有访问。
方案2:使用Dart扩展方法
如果拆分的逻辑不需要访问Bloc的私有成员,只是对Bloc公开属性/输入参数做处理,可以用扩展方法实现:
// 拆分到单独文件 extension MyBlocExtensions on MyBloc { MyData initData(MyData dataRaw) { // 逻辑实现 } MyData doSomeMore(MyData dataProc) { // 逻辑实现 } } // 原Bloc中直接调用即可,和内置方法无差别 Stream<LogicChainState> _mapLoadRequestedToState() async* { final dataRaw = loadData(); final dataProc = initData(dataRaw); yield doSomeMore(dataProc); }
方案3:领域服务层拆分纯业务逻辑
如果抽离的逻辑是和Bloc框架无关的纯业务计算、数据处理逻辑,可以单独封装为领域服务类,通过构造注入到Bloc中使用,这种方式的可测试性最高,逻辑也可以复用到其他组件:
// 独立的服务类 class MyDataService { MyData initData(MyData dataRaw) { // 逻辑实现 } MyData doSomeMore(MyData dataProc) { // 逻辑实现 } } // Bloc构造时注入服务 class MyBloc extends Bloc<MyEvent, MyState> { final MyDataService dataService; MyBloc(this.dataService) : super(MyInitialState()); Stream<LogicChainState> _mapLoadRequestedToState() async* { final dataRaw = loadData(); final dataProc = dataService.initData(dataRaw); yield dataService.doSomeMore(dataProc); } }
方案选择建议
- 如果拆分的逻辑和当前Bloc强绑定、需要访问Bloc内部成员,优先选Mixin方案
- 如果拆分的是纯工具性质的逻辑、不需要访问Bloc私有属性,选扩展方法
- 如果拆分的是可复用的纯业务逻辑、需要做单独单元测试,选领域服务方案
内容的提问来源于stack exchange,提问作者w461
相关产品推荐
相关产品推荐

