我正在使用 Spring Boot 3 开始一个新项目。我们仍处于项目的早期阶段,仍在定义事物。所以,话虽这么说。这是我的问题:
我要解决的问题: 旨在处理所有业务逻辑的服务层在实体之间共享公共功能,例如:CRUD 功能等。
建议: 创建一个具有所有常用功能的通用接口。然后:创建一个将实现此接口并覆盖的抽象类;为什么要抽象是因为我想防止向父界面添加新功能并遍历所有已实现的案例。
这是我实现的一个例子:
// Project stucture.
main-project
|-src
|--main
|-java
|-com.project
|-entities
|-repositories
|-service
| |-implementation
|-rest
现在 entities, repositories 和 rest package 里面的内容大家都知道,下面是我的服务包实现:
BaseCommonOperationInterface
public interface BaseCommonOperationInterface<E, V> {
E createItemOf(V requestDto);
E updateItemfrom(final Long identifier, V requestDto);
void deleteItem(final Long identifier);
Optional<E> findSingleRecordByIdentifier(Long skillDicCategoryId);
List<E> listAllItems();
//more common function...
}
商业基础摘要
puiblic abstract class BusinessBaseAbstract<E, V> implements BaseCommonOperationInterface<E, V>{
//Here override all methods from interface...
@Override
public List<E> listAllItems() {
return Collections.emptyList();
}
//...
}
词典服务
public interface DictionaryService implement BaseCommonOperationInterface<DictionaryEntity, DictionaryrequestDto>{}
DictionaryServiveImpl
@RequieredArgConstructor
@Service
public class DictionaryServiveImpl extends BusinessBaseAbstract<DictionaryEntity, DictionaryrequestDto> implements DictionaryService{
private final DictionaryRepository dictionaryRepository;
//I can override eather single common function or all of them
@override
public List<DictionaryEntity> listAllItems(){
return dictionaryRepository.findAll()
}
// all the methods I need overrided here...
}
词典控制器
@RestController
public class DictionaryController{
private final DictionaryService service;
@GetMapping("/dictionary")
public List<DictionarEntity> getAllofThem(){
return service.listAllItems();
}
//Here rest of implementations...
}
为什么不从控制器调用 DictionaryRepository 因为我们希望尽可能保持 Rest Controller 干净并将所有业务逻辑委托给服务包。
这个模式有意义吗? 有优点和缺点吗? 还有其他模式可以应用于抽象的通用功能吗?
这不是个好主意。
当你想在不知道具体类的情况下使用实现接口的类的实例时,拥有多个实现接口的类是一个好主意。
如果您有所有
XxxServiceImpl
类的集合,并且想在每个类上运行 BaseCommonOperationInterface
的方法,那么该接口将很有用。但这通常不是服务的使用方式——它们被明确地注入到需要它们的控制器类中。
拥有一个通用接口意味着当您将方法添加到一项服务时,您需要将它添加到所有服务——但也许服务是不同的。
你提出了一个抽象基类,这样你就可以对一些服务有一个无操作的实现,但这只会让你的服务变得混乱——我们应该期望调用这个方法做某事还是不做?服务的用户会想知道为什么一个特定的服务有一个它不需要的方法,不知道接口需要它,而实现什么都不做。
最后,如果您确实有充分的理由强制所有服务都存在一个方法,那么是的,使用一个接口,但是不要在抽象类中放置一个空的实现。
如果没有那个抽象类,你将不得不考虑:这个服务需要什么样的实现来实现新的方法?如果存在默认实现,当添加新方法时,ir 很容易错过对服务的思考。