如何在Dart/Flutter中使用injectable实现通用工厂?
解决方案:实现通用工厂注册,避免重复编写工厂类
一、基于Injectable的优化方案
1. 注入函数类型替代工厂类
Injectable支持注入函数类型,通过定义通用函数别名,直接注入创建实例的函数,无需单独编写工厂类:
首先定义通用工厂函数的别名:
typedef FactoryFunc<T> = T Function();
然后编写业务类和实例创建函数:
import 'package:injectable/injectable.dart'; @singleton class Foo { final FactoryFunc<Bar> _barFactory; // 直接注入创建Bar的函数 Foo(this._barFactory); void doSomething() { var bar = _barFactory(); // 调用函数创建实例 bar.blah(); } } // 定义Bar的创建函数 @injectable Bar createBar() => const Bar(); @injectable class Bar { const Bar(); void blah() { /* ... */ } }
最后在configureDependencies中注册函数类型(若自动生成未覆盖,可手动补充):
getIt.registerFactory<FactoryFunc<Bar>>(() => createBar);
2. 通用Factory类结合模块注册
如果你更倾向于保留工厂类结构,可以创建通用Factory<T>类,通过Injectable的模块集中注册,避免为每个类型编写单独工厂类:
// 通用工厂类 class Factory<T> { final T Function() create; const Factory(this.create); } // 模块类,集中注册所有工厂 @module abstract class FactoriesModule { @injectable Factory<Bar> get barFactory => Factory(() => const Bar()); // 其他类型的工厂直接在这里添加即可 @injectable Factory<Baz> get bazFactory => Factory(() => Baz()); }
然后在Foo中注入对应的泛型工厂:
@singleton class Foo { final Factory<Bar> _barFactory; Foo(this._barFactory); void doSomething() { var bar = _barFactory.create(); bar.blah(); } }
二、换用GetIt直接实现(无需Injectable)
如果放弃Injectable,直接使用GetIt可以更灵活实现通用工厂:
- 注册工厂函数:
void configureDependencies() { final getIt = GetIt.instance; // 注册Bar的工厂函数,每次调用返回创建Bar的函数 getIt.registerFactory<FactoryFunc<Bar>>(() => () => const Bar()); }
- 在业务类中注入并使用:
typedef FactoryFunc<T> = T Function(); class Foo { final FactoryFunc<Bar> _barFactory; Foo(this._barFactory); void doSomething() { var bar = _barFactory(); bar.blah(); } }
注:若直接调用
getIt<Bar>()(需用getIt.registerFactory(() => Bar())注册),虽能创建实例,但会让类直接依赖GetIt,不符合解耦原则,更推荐注入工厂函数的方式。
三、使用Riverpod实现(适用于Flutter)
如果是Flutter项目,Riverpod提供声明式依赖注入方案,同样可实现通用工厂:
- 定义工厂Provider:
import 'package:flutter_riverpod/flutter_riverpod.dart'; // 定义创建Bar的工厂Provider final barFactoryProvider = Provider<Bar Function()>((ref) => () => const Bar()); class Bar { const Bar(); void blah() {} }
- 在消费类中注入使用:
class Foo { final Bar Function() _barFactory; Foo(this._barFactory); void doSomething() { var bar = _barFactory(); bar.blah(); } } // 在Widget或其他地方获取Foo实例时,传入工厂函数 final fooProvider = Provider<Foo>((ref) { final barFactory = ref.read(barFactoryProvider); return Foo(barFactory); });
内容的提问来源于stack exchange,提问作者Tar
相关产品推荐
相关产品推荐

