我正在使用Sping Boot 3启动一个新项目。我们仍处于项目的早期阶段,仍在定义事物。所以,说。这是我的问题:
**我想解决的问题:**服务层负责处理所有业务逻辑,在实体之间共享公共功能,例如:CRUD函数和其他。
**建议:**创建一个包含所有常用函数的Generic接口,然后:创建一个将实现此接口并重写的抽象类;为什么是抽象的,因为我想防止在父接口中添加新函数的过程,并遍历所有实现的情况。
下面是我实现的一个例子:
// Project stucture.
main-project
|-src
|--main
|-java
|-com.project
|-entities
|-repositories
|-service
| |-implementation
|-rest
现在我们都知道实体、仓库和rest包里面有什么,下面是我的服务包实现:
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...
}
DictionaryController
@RestController
public class DictionaryController{
private final DictionaryService service;
@GetMapping("/dictionary")
public List<DictionarEntity> getAllofThem(){
return service.listAllItems();
}
//Here rest of implementations...
}
为什么不从控制器调用DictionaryRepository,因为我们希望尽可能地保持Rest控制器干净,并将所有业务逻辑委托给Service包。
这个模式有意义吗?有优点和缺点吗?有没有其他模式可以应用于抽象的公共功能?
1条答案
按热度按时间lymnna711#
这不是个好主意。
当你想使用实现接口的类的示例而不知道它们的具体类时,拥有多个实现接口的类是一个好主意。
如果你有一个所有
XxxServiceImpl
类的集合,并希望在每个类上运行一个来自BaseCommonOperationInterface
的方法,那么这个接口将是有用的。但这不是通常使用服务的方式--它们被显式地注入到需要它们的控制器类中。拥有一个公共接口意味着当您将一个方法添加到一个服务时,您需要将它添加到所有服务中--但这些服务可能是不同的。
您提出了一个抽象基类,以便可以为某些服务提供无操作的实现,但这只会使您的服务感到困惑-我们应该期望调用此方法来做某事吗?服务的用户会想知道为什么特定的服务上有一个它不需要的方法,而不知道接口需要它,并且实现什么也不做。
最后,如果你确实有一个很好的理由强制一个方法存在于你的所有服务上,那么是的,使用一个接口,但是不要在抽象类中放置一个空的实现。
如果没有这个抽象类,你将不得不考虑:这个服务需要什么样的实现来实现新方法?如果存在默认的实现,那么当添加新方法时,很容易忽略服务。