辅助数据模型(Data Transfer Object, DTO 或 Auxiliary Data Model) 是一种设计模式,用于在应用的不同层或模块之间传递数据。它通常用于简化数据的传输、减少直接依赖核心模型的耦合性,或者满足特定的转换需求(如序列化为 JSON)。
实际的应用场景为:在关联数据进行编码或解码(例如导出到JSON),可以使用辅助数据模型,创建普通的结构体(不包含Codable协议),通过辅助数据模型进行数据的导出,而非直接操作 SwiftData 模型。
以下是关于辅助数据模型的详细解释:
辅助数据模型的核心特性
1、轻量化:
仅包含需要传递的数据字段,去掉与框架、业务逻辑相关的复杂功能(如数据库关系、计算属性等)。
2、解耦:
它是核心数据模型的简化或独立版本,可以减少对底层实现(如数据库、框架)的直接依赖。
常用于与 API 或外部系统交互时,避免直接暴露内部模型。
3、方便转换:
它可以自由定义数据的结构和类型,以适配不同的需求(例如格式化日期或计算衍生字段)。
4、安全性:
可以通过设计,只暴露安全的数据,保护内部业务逻辑和结构不受外部影响。
辅助数据模型的应用场景
1、与网络交互:
在调用 RESTful API 或 GraphQL 接口时,使用 DTO 对接数据,而不是直接使用内部模型。
例如:将内部复杂的关系模型转换为扁平化的 JSON 对象。
2、数据导出:
当需要将数据导出到文件(如 JSON、CSV)时,DTO 提供了更清晰的结构。
例如:导出时省略敏感字段或内部框架相关字段。
3、前端展示:
在视图层只需要特定的字段时,可以使用 DTO 来优化性能和简化逻辑。
4、解耦模块:
在多模块项目中,用 DTO 传递数据可以减少模块之间的直接依赖。
辅助数据模型的设计
以下是一个辅助数据模型的典型设计过程:
1、定义 DTO 类:
提取核心模型中需要传递的数据字段,省略与业务无关的内容。
可以增加额外的衍生字段(如格式化后的日期、计算值)。
2、提供转换方法:
在核心数据模型中添加方法,将其转换为 DTO,或者通过 DTO 初始化核心数据模型。
示例:在存钱罐应用中的应用
1、核心模型
@Model
class PiggyBank: Identifiable {
let id = UUID()
var name: String
var targetAmount: Double
var amount: Double
var creationDate: Date
@Relationship var records: [SavingsRecord]
init(name: String, targetAmount: Double, amount: Double, creationDate: Date) {
self.name = name
self.targetAmount = targetAmount
self.amount = amount
self.creationDate = creationDate
}
}
2、辅助数据模型
struct PiggyBankDTO: Codable {
var name: String
var targetAmount: Double
var amount: Double
var creationDate: String // 格式化后的日期
var savingsCount: Int // 存取记录的数量(衍生字段)
init(from piggyBank: PiggyBank) {
self.name = piggyBank.name
self.targetAmount = piggyBank.targetAmount
self.amount = piggyBank.amount
self.creationDate = Self.formatDate(piggyBank.creationDate)
self.savingsCount = piggyBank.records.count
}
private static func formatDate(_ date: Date) -> String {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
return formatter.string(from: date)
}
}
3、转换方法
let piggyBank = PiggyBank(name: "旅行基金", targetAmount: 10000, amount: 2500, creationDate: Date())
// 从核心模型转换为辅助模型
let dto = PiggyBankDTO(from: piggyBank)
// 将 DTO 转换为 JSON
if let jsonData = try? JSONEncoder().encode(dto),
let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
}
输出示例
{
"name": "旅行基金",
"targetAmount": 10000,
"amount": 2500,
"creationDate": "Jan 11, 2025",
"savingsCount": 0
}
使用辅助数据模型的好处
1、更清晰的数据结构:DTO 仅包含前端或外部系统需要的字段,减少冗余。
2、增强安全性:避免暴露敏感信息或内部实现。
3、提高灵活性:可以在不修改核心模型的情况下,快速适配不同的数据需求。
4、减少耦合:核心模型和外部需求之间通过 DTO 作为桥梁解耦,方便模型的独立演进。
总结
辅助数据模型的主要功能是将原有的数据模型做了功能上的分离,保障了内部模型不被修改,对外部接口使用辅助数据类型进行交互。在实际应用中,也可以先创建核心模型,延展功能可放置在辅助数据模型中,增加灵活性。