model-patterns
10
总安装量
7
周安装量
#30212
全站排名
安装命令
npx skills add https://github.com/kaakati/rails-enterprise-dev --skill model-patterns
Agent 安装分布
antigravity
6
claude-code
6
opencode
6
codex
6
windsurf
5
Skill 文档
Model Patterns
Entity (Domain Layer)
// lib/domain/entities/user.dart
import 'package:equatable/equatable.dart';
class User extends Equatable {
final String id;
final String name;
final String email;
final DateTime createdAt;
final DateTime? updatedAt;
const User({
required this.id,
required this.name,
required this.email,
required this.createdAt,
this.updatedAt,
});
List<Object?> get props => [id, name, email, createdAt, updatedAt];
User copyWith({
String? name,
String? email,
DateTime? updatedAt,
}) {
return User(
id: id,
name: name ?? this.name,
email: email ?? this.email,
createdAt: createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
}
Model (Data Layer)
Basic Model with JSON Serialization
// lib/data/models/user_model.dart
import '../../domain/entities/user.dart';
class UserModel extends User {
const UserModel({
required super.id,
required super.name,
required super.email,
required super.createdAt,
super.updatedAt,
});
factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String,
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: json['updated_at'] != null
? DateTime.parse(json['updated_at'] as String)
: null,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
'created_at': createdAt.toIso8601String(),
if (updatedAt != null) 'updated_at': updatedAt!.toIso8601String(),
};
}
User toEntity() {
return User(
id: id,
name: name,
email: email,
createdAt: createdAt,
updatedAt: updatedAt,
);
}
factory UserModel.fromEntity(User entity) {
return UserModel(
id: entity.id,
name: entity.name,
email: entity.email,
createdAt: entity.createdAt,
updatedAt: entity.updatedAt,
);
}
}
Model with Nested Objects
class OrderModel extends Order {
final List<OrderItemModel> itemModels;
const OrderModel({
required super.id,
required super.userId,
required super.total,
required this.itemModels,
}) : super(items: itemModels);
factory OrderModel.fromJson(Map<String, dynamic> json) {
return OrderModel(
id: json['id'],
userId: json['user_id'],
total: json['total'].toDouble(),
itemModels: (json['items'] as List)
.map((item) => OrderItemModel.fromJson(item))
.toList(),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'user_id': userId,
'total': total,
'items': itemModels.map((item) => item.toJson()).toList(),
};
}
}
Model with Enum
enum UserRole { admin, user, guest }
extension UserRoleX on UserRole {
String toJson() => name;
static UserRole fromJson(String json) {
return UserRole.values.firstWhere(
(role) => role.name == json,
orElse: () => UserRole.guest,
);
}
}
class UserModel extends User {
final UserRole roleValue;
const UserModel({
required super.id,
required super.name,
required this.roleValue,
}) : super(role: roleValue);
factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
id: json['id'],
name: json['name'],
roleValue: UserRoleX.fromJson(json['role']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'role': roleValue.toJson(),
};
}
}
Immutability Patterns
Using Freezed (Recommended)
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user_model.freezed.dart';
part 'user_model.g.dart';
class UserModel with _$UserModel {
const factory UserModel({
required String id,
required String name,
required String email,
DateTime? updatedAt,
}) = _UserModel;
factory UserModel.fromJson(Map<String, dynamic> json) =>
_$UserModelFromJson(json);
}
Manual Immutability
class UserModel {
final String id;
final String name;
final String email;
const UserModel({
required this.id,
required this.name,
required this.email,
});
UserModel copyWith({
String? name,
String? email,
}) {
return UserModel(
id: id,
name: name ?? this.name,
email: email ?? this.email,
);
}
}
Equality Patterns
Using Equatable
import 'package:equatable/equatable.dart';
class User extends Equatable {
final String id;
final String name;
const User({required this.id, required this.name});
List<Object?> get props => [id, name];
}
Manual Equality
class User {
final String id;
final String name;
const User({required this.id, required this.name});
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is User && other.id == id && other.name == name;
}
int get hashCode => id.hashCode ^ name.hashCode;
}