docs/architecture/import-export-interface-design.md
用户提出了一个非常重要的架构观点:"当前由DataManager来实现import和export的具体实现不合理。应该抽象一个接口定义,有导入导出方法。让各个service类去继承,如 IModelManager、IPreferenceService等。要求他们必须实现这个接口。DataManager只负责总体协调,具体实现由各个类负责。"
/**
* 可导入导出的服务接口
* 所有需要参与数据导入导出的服务都应该实现此接口
*/
export interface IImportExportable {
/**
* 导出服务的所有数据
* @returns 服务数据的JSON表示
*/
exportData(): Promise<any>;
/**
* 导入数据到服务
* @param data 要导入的数据
* @returns 导入结果
*/
importData(data: any): Promise<ImportExportResult>;
/**
* 获取服务的数据类型标识
* 用于在导入导出JSON中标识数据类型
*/
getDataType(): string;
/**
* 验证数据格式是否正确
* @param data 要验证的数据
* @returns 是否为有效格式
*/
validateData(data: any): boolean;
}
// 所有需要导入导出的服务都继承IImportExportable
export interface IModelManager extends IImportExportable { /* ... */ }
export interface IPreferenceService extends IImportExportable { /* ... */ }
export interface ITemplateManager extends IImportExportable { /* ... */ }
export interface IHistoryManager extends IImportExportable { /* ... */ }
export class DataCoordinator implements IDataManager {
private readonly services: IImportExportable[];
// 直接通过构造函数注入所有服务,简单直接
constructor(services: IImportExportable[]) {
this.services = services;
}
/**
* 导出所有数据 - 只负责协调
*/
async exportAllData(): Promise<ExportData> {
const data: Record<string, any> = {};
// 并行导出所有服务的数据
const exportPromises = this.services.map(async (service) => {
const dataType = service.getDataType();
const serviceData = await service.exportData();
data[dataType] = serviceData;
});
await Promise.all(exportPromises);
return { version: 1, timestamp: Date.now(), data };
}
/**
* 导入所有数据 - 只负责协调
*/
async importAllData(exportData: ExportData): Promise<ImportExportResult> {
// 并行导入所有服务的数据
const importPromises = Object.entries(exportData.data).map(async ([dataType, serviceData]) => {
const service = this.services.find(s => s.getDataType() === dataType);
if (service) {
return await service.importData(serviceData);
}
});
const results = await Promise.all(importPromises);
// 汇总结果...
}
}
// 使用示例:简单的工厂函数
export function createDataCoordinator(services: IImportExportable[]): DataCoordinator {
return new DataCoordinator(services);
}
// ❌ DataManager需要了解每个服务的具体实现
class DataManager {
async exportAllData() {
const userSettings = await this.preferenceService.getAll();
const models = await this.modelManager.getAllModels();
const templates = await this.templateManager.listTemplates();
const history = await this.historyManager.getAllRecords();
// DataManager需要知道每个服务的具体方法名和返回格式
}
}
// ✅ DataCoordinator只负责协调,不关心具体实现
class DataCoordinator {
constructor(services: IImportExportable[]) {
this.services = services; // 简单的依赖注入
}
async exportAllData() {
// 统一调用每个服务的exportData()方法
const exportPromises = this.services.map(async (service) => {
const dataType = service.getDataType();
data[dataType] = await service.exportData();
});
}
}
// 使用时直接传入所有服务
const coordinator = new DataCoordinator([
modelManager,
preferenceService,
templateManager,
historyManager
]);
export class ModelManager implements IModelManager {
async exportData(): Promise<ModelConfig[]> {
return await this.getAllModels();
}
async importData(data: any): Promise<ImportExportResult> {
if (!this.validateData(data)) {
return { success: false, message: 'Invalid model data format' };
}
// 具体导入逻辑...
}
getDataType(): string {
return 'models';
}
validateData(data: any): boolean {
return Array.isArray(data) && data.every(/* 验证逻辑 */);
}
}
export class PreferenceService implements IPreferenceService {
async exportData(): Promise<Record<string, string>> {
return await this.getAll();
}
async importData(data: any): Promise<ImportExportResult> {
if (!this.validateData(data)) {
return { success: false, message: 'Invalid preference data format' };
}
// 具体导入逻辑...
}
getDataType(): string {
return 'userSettings';
}
validateData(data: any): boolean {
return typeof data === 'object' && /* 验证逻辑 */;
}
}
IImportExportable接口IImportExportable接口在重构过程中,我们差点引入了破坏性更新:
// ❌ 原来的接口(破坏性更新)
async exportAllData(): Promise<ExportData>;
async importAllData(data: ExportData): Promise<ImportExportResult>;
// ✅ 修正后的接口(保持兼容)
async exportAllData(): Promise<string>;
async importAllData(dataString: string): Promise<ImportExportResult>;
这次重构体现了优秀的架构设计原则:
用户的建议非常准确,不仅指出了架构问题,还及时发现了兼容性问题,让系统更加稳定和可维护。