You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据对象类型将文档对象存入对应Repository

最优实现方案:策略+工厂模式结合类型映射

1. 定义基础抽象层

先统一所有文档的父类与Repository通用接口,确保子类遵循一致规范:

// 所有文档的父类,封装公共属性
public abstract class BaseDocument {
    private Long id;
    private LocalDateTime createTime;
    // getter/setter省略
}

// 通用Repository接口,定义统一存储方法
public interface DocumentRepository<T extends BaseDocument> {
    void save(T document);
}

实现具体文档类与对应Repository:

// 具体文档实现
public class ImageDocument extends BaseDocument {}
public class ArticleDocument extends BaseDocument {}
public class VideoDocument extends BaseDocument {}

// 具体Repository实现
@Repository // Spring环境下可添加该注解交由容器管理
public class ImageDocumentRepository implements DocumentRepository<ImageDocument> {
    @Override
    public void save(ImageDocument document) {
        // 图片文档专属存储逻辑
    }
}

@Repository
public class ArticleDocumentRepository implements DocumentRepository<ArticleDocument> {
    @Override
    public void save(ArticleDocument document) {
        // 文章文档专属存储逻辑
    }
}

@Repository
public class VideoDocumentRepository implements DocumentRepository<VideoDocument> {
    @Override
    public void save(VideoDocument document) {
        // 视频文档专属存储逻辑
    }
}

2. 实现类型映射工厂

通过工厂类维护文档类型与Repository的映射关系,彻底消除switch/if-else:

纯Java原生实现

public class DocumentRepositoryFactory {
    // 静态映射表,初始化时绑定类型与Repository实例
    private static final Map<Class<? extends BaseDocument>, DocumentRepository<? extends BaseDocument>> REPO_MAP = new HashMap<>();

    static {
        REPO_MAP.put(ImageDocument.class, new ImageDocumentRepository());
        REPO_MAP.put(ArticleDocument.class, new ArticleDocumentRepository());
        REPO_MAP.put(VideoDocument.class, new VideoDocumentRepository());
    }

    @SuppressWarnings("unchecked")
    public static <T extends BaseDocument> DocumentRepository<T> getRepository(Class<T> documentClass) {
        DocumentRepository<? extends BaseDocument> repo = REPO_MAP.get(documentClass);
        if (repo == null) {
            throw new IllegalArgumentException("Unsupported document type: " + documentClass.getName());
        }
        return (DocumentRepository<T>) repo;
    }
}

Spring环境优化实现(推荐)

如果是Spring项目,可让工厂从容器中获取Bean,避免手动实例化:

@Component
public class SpringDocumentRepositoryFactory implements ApplicationContextAware {
    private ApplicationContext context;
    // 维护文档类型与Repository类的映射
    private static final Map<Class<? extends BaseDocument>, Class<? extends DocumentRepository<?>>> REPO_CLASS_MAP = new HashMap<>();

    static {
        REPO_CLASS_MAP.put(ImageDocument.class, ImageDocumentRepository.class);
        REPO_CLASS_MAP.put(ArticleDocument.class, ArticleDocumentRepository.class);
        REPO_CLASS_MAP.put(VideoDocument.class, VideoDocumentRepository.class);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    @SuppressWarnings("unchecked")
    public <T extends BaseDocument> DocumentRepository<T> getRepository(Class<T> documentClass) {
        Class<? extends DocumentRepository<?>> repoClass = REPO_CLASS_MAP.get(documentClass);
        if (repoClass == null) {
            throw new IllegalArgumentException("Unsupported document type: " + documentClass.getName());
        }
        return (DocumentRepository<T>) context.getBean(repoClass);
    }
}

3. Controller中使用

无需注入所有Repository,直接通过工厂获取对应实例完成存储:

@RestController
@RequestMapping("/documents")
public class DocumentController {
    // Spring环境下注入工厂
    private final SpringDocumentRepositoryFactory repositoryFactory;

    public DocumentController(SpringDocumentRepositoryFactory repositoryFactory) {
        this.repositoryFactory = repositoryFactory;
    }

    @PostMapping
    public ResponseEntity<Void> saveDocument(@RequestBody BaseDocument document) {
        DocumentRepository<BaseDocument> repository = repositoryFactory.getRepository(document.getClass());
        repository.save(document);
        return ResponseEntity.ok().build();
    }
}

4. 扩展说明

新增文档类型时,仅需三步:

  1. 实现新的BaseDocument子类
  2. 实现对应DocumentRepository接口
  3. 在工厂的映射表中添加一行类型绑定

完全符合开闭原则,没有冗余的判断逻辑,也无需注入所有Repository实例。


内容的提问来源于stack exchange,提问作者bblex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 23:12:18