1

这是一个什么是最佳实践的问题。

我正在使用颤振构建一个应用程序,我有以下要求。

  1. 我有本地(安装在设备上)和远程(安装在服务器上)数据库。

  2. 我必须为本地数据库构建存储库。我有很多选择(SQLITE、Hive 等)。我必须保持数据库的选择与应用程序(存储库模式)松散耦合。

  3. 我必须使用 BLOC 模式进行状态管理。

我苦苦挣扎的一点是,对于每种类型的数据库,实体模型(我来自实体框架背景,因此称它为实体模型。我不知道你怎么称呼它)是不同的。

例如,

SQLLite (Moor) 的模型如下所示

class ToDosSqlLite extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
}

Hive 的模型如下所示。

class ToDosHive extends HiveObject {
  final int id;

  final String title;

  Person(this.id, this.title);
}

对于任何其他选择的数据库,模型看起来会有所不同。

我有如下的存储库类。

abstract class LocalToDoRepository{
  List<What should be the type here?> getAll();
}

class SqlLiteToDoRepository extends LocalToDoRepository{
   ///overriding won't work here as Type is different from the base class method
   @override
   List<ToDosSqlLite> getAll(){///implementation}
}

class HiveToDoRepository extends LocalToDoRepository{
   ///overriding won't work here as Type is different from the base class method
   @override
   List<ToDosHive> getAll(){///implementation}
}

在 SqlLiteToDoRepository 中,getAll()方法返回 a List<ToDosSqlLite>,在 HiveToDoRepository 中,相同的方法返回 a List<ToDosHive>

下面是我的集团

class ToDoBloc extends Bloc<ToDoEvent, ToDoState>{
  final LocalToDoRepository localToDoRepository;
  ///localToDoRepository object is dependency injected . If I want to use SQLite, I will inject 
  ///SqlLiteToDoRepository and so on.
  ToDoBloc ({@required this.localToDoRepository}): super(ToDoInitialState());
}

我如何以优雅的方式进行这种抽象?如果您有任何想法,请提出建议。

提前致谢。

4

2 回答 2

2

你可以尝试这样的事情:

final _mockedSql = [
  ToDoSqlLite(1, 'Implement dependency inversion principle'),
  ToDoSqlLite(2, 'Implement repository pattern'),
];

final _mockedHive = [
  ToDoHive(1, 'Feed the cat'),
  ToDoHive(2, 'Wash dishes'),
];

abstract class ToDoBase<A, B> {
  abstract final A id;
  abstract final B title;
}

class ToDoBusinessEntity {
  final int id;
  final String title;
  ToDoBusinessEntity(this.id, this.title);
  
  @override
  String toString() => 'ToDoBusinessEntity {id: $id, title: $title}';
}

class ToDoSqlLite implements ToDoBase<int, String> {
  final int id;
  final String title;
  ToDoSqlLite(this.id, this.title);
}

class ToDoHive implements ToDoBase<Object, Object> {
  final Object id;
  final Object title;
  ToDoHive(this.id, this.title);
}

abstract class LocalToDoRepository<T extends ToDoBase, Z>{
  abstract final DataSource<T> dataSource;
  List<Z> getAll();
  List<Z> _sourceToEntity(List<T> sourceList);
}

abstract class DataSource<T> {
  List<T> getAll();
}

class SqlDataSource implements DataSource<ToDoSqlLite> {
  List<ToDoSqlLite> getAll() => _mockedSql;
}

class HiveDataSource implements DataSource<ToDoHive> {
  List<ToDoHive> getAll() => _mockedHive;
}

class SqlLiteToDoRepository implements LocalToDoRepository<ToDoSqlLite, ToDoBusinessEntity>{
  DataSource<ToDoSqlLite> dataSource;
  
  SqlLiteToDoRepository(this.dataSource);
  
  @override
  List<ToDoBusinessEntity> _sourceToEntity(List<ToDoSqlLite> source) => source.map<ToDoBusinessEntity>((e) => ToDoBusinessEntity(e.id, e.title)).toList();
  
   @override
   List<ToDoBusinessEntity> getAll() => _sourceToEntity(dataSource.getAll());
}

class HiveToDoRepository implements LocalToDoRepository<ToDoHive, ToDoBusinessEntity>{
    DataSource<ToDoHive> dataSource;
  
  HiveToDoRepository(this.dataSource);

   @override
   List<ToDoBusinessEntity> getAll() => _sourceToEntity(dataSource.getAll());
  
    @override
  List<ToDoBusinessEntity> _sourceToEntity(List<ToDoHive> source) => source.map<ToDoBusinessEntity>((e) => ToDoBusinessEntity(int.parse(e.id.toString()), e.title.toString())).toList();
}

class Bloc {
  final LocalToDoRepository repository;
  Bloc(this.repository) {
    print(repository.getAll());
  }
}

void main() {
  final blocSql = Bloc(SqlLiteToDoRepository(SqlDataSource()));
  final blocHive = Bloc(HiveToDoRepository(HiveDataSource()));
}

这输出

[ToDoBusinessEntity {id: 1, title: Implement dependency inversion principle}, ToDoBusinessEntity {id: 2, title: Implement repository pattern}]
[ToDoBusinessEntity {id: 1, title: Feed the cat}, ToDoBusinessEntity {id: 2, title: Wash dishes}]
于 2021-06-21T18:49:12.717 回答
0

您可能需要引入名为 todo 的第三类

class Todo {
  final int id;

  final String title;

  Todo(this.id, this.title);

  // implement the required conversion 
  Todo.fromHive(......)
  Todo.fromSqf(.....)
}

然后,在所有 repos 和接口中使用这个新模型

于 2021-04-23T07:35:03.650 回答