如何根据对象类型将文档对象存入对应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. 扩展说明
新增文档类型时,仅需三步:
- 实现新的
BaseDocument子类 - 实现对应
DocumentRepository接口 - 在工厂的映射表中添加一行类型绑定
完全符合开闭原则,没有冗余的判断逻辑,也无需注入所有Repository实例。
内容的提问来源于stack exchange,提问作者bblex
相关产品推荐
相关产品推荐

