我做了一些相反的建议,但我只记得在我的上一个项目中我做了类似的事情,它是为 Firebase 数据库,但对于 sqflite。
我创建了一个BaseItem 抽象类,带有一个key,所有模型都将从那个类继承。
我还创建了一个 BaseProvider 抽象类,它需要一个 BaseItem 并定义访问模型的简单方法。
upsert 和 delete 方法位于 FirebaseBaseProvider 中,它扩展了 BaseProvider。
我将在此处粘贴部分内容(删除了很多内容以使其更易于理解):
abstract class BaseItem {
const BaseItem({this.key});
final String key;
}
abstract class BaseProvider<T extends BaseItem> {
Future<List<T>> find();
Future<BaseKey> upsert(T item);
Future<int> delete(T item);
}
abstract class FirebaseBaseProvider<T extends BaseItem> {
// Abstract methods which need to be implemented
T fromMap(BaseKey key, dynamic map);
Map<String, dynamic> toJson(BaseKey key, T item);
Future<DatabaseReference> getReference(BaseKey base) async { ... }
BaseKey compileKey(T item, {String useKey}) { ... }
Future<List<T>> find() async {
List<T> result = new List();
// my implementation doesnt work like this,
// as it's firebase based, but this would
// be the place in a Sqflite implementation to use
// fromMap and load the items
return result;
}
Future<BaseKey> upsert(T item) async {
if (item == null) return null;
BaseKey key = compileKey(item);
(await getReference(key)).set(toJson(key, item));
return key;
}
Future<int> delete(T item) async {
if (item == null) return null;
if (item.key != null && item.key != "") {
(await getReference(compileKey(item))).remove();
}
return 0;
}
}
然后,为了实现 News 模型或任何其他模型,我将通过简单地定义其内容来创建它,如下所示:
class News extends BaseItem {
News({String key, this.creation, this.messageSubject, this.messageBody}) : super(key: key);
final DateTime creation;
final String messageSubject;
final String messageBody;
bool operator ==(o) => o is News && (o.key == key);
int get hashCode => key.hashCode;
}
它需要特定的提供者,它只实现 toJson 和 fromMap 方法,就像这样:
class NewsProvider extends FirebaseBaseProvider<News> {
@override
Map<String, dynamic> toJson(BaseKey key, News news) {
return {
"creation": news.creation,
"messageSubject": news.messageSubject,
"messageBody": news.messageBody,
};
}
@override
News fromMap(BaseKey key, dynamic map) {
DateTime creation = map["creation"] == null ? null : DateTime.tryParse(map["creation"] as String);
return new News(
key: key.child.key,
creation: creation,
messageSubject: map["messageSubject"] as String,
messageBody: map["messageBody"] as String,
);
}
}
最后,NewProvider 提供了find、upsert 和delete 方法,但它们的实现基于抽象类,如您所愿,仅适用于所有模型的一种实现。
当然,我的实现要复杂得多,因为 Firebase 需要不同的方法来获取/加载项目,而且 find 方法最终必须在每个模型特定的提供者中有所不同。但是,很多东西都可以简化。
我在评论中说的是最后一个类,即具有 toJson 和 fromMap 特定实现的特定 NewsProvider 也可以通过在 News 模型类中使用注释来概括,但是带来了很多问题和晦涩难懂 - 在我看来,当然 - 这不值得。