service层中的接口是干什么用的?
请问各位在使用spring开发web应用时,有没有遇到service层中的接口被多实现的场景?接口-单实现类写吐了不知道有什么作用
interface IUserService{
User getUserByUserName(String username);
}
p c UserServiceAAA implements IUserService{
@Override
public User getUserByUserName(String username){
return userDao.去分公司的库里查();
}
}
p c UserServiceBBB implements IUserService{
@Override
public User getUserByUserName(String username){
return rpc.调用当地劳动局的接口("https://peoplexxx.com");
}
}
即使遇到多个实现类,这个接口被注入的地方也需要策略来决定用哪个实现类吧,直接在选择策略的地方决定注入哪个service bean不就行了吗?我在选择这两个实现类的时候还是要用spring @Qualifier
注解决定注哪一个,那改类名和改@Qualifier
注解值好像也没多大区别吧,甚至还更简洁了,那这个接口存在的意义在哪里?
p c UserController{
@Qualifier("serviceAAA")
@Autowired
private IUserService userService;
@Qualifier("serviceBBB")
@Autowired
private IUserService userService;
//===============
@Autowired
private UserServiceAAA userServiceAAA;
@Autowired
private UserServiceBBB userServiceBBB;
}
回复
1个回答

test
2024-06-21
其实这种写法本质上就是 策略模式
可以看一下这个教程策略模式|菜鸟教程我觉得优点就是你可以保证每个实现类一定都有相同的行为,并且在新增一个实现类也不会影响到原来的实现类(开闭原则)缺点当然也有,灵活度被限制了,你写起来确实会比较烦(新增一种实现类型就要多写一个实现类),属于是开发的时候麻烦维护的时候容易
即使遇到多个实现类,这个接口被注入的地方也需要策略来决定用哪个实现类吧,直接在选择策略的地方决定注入哪个service bean不就行了吗?我在选择这两个实现类的时候还是要用spring @Qualifier注解决定注哪一个,那改类名和改@Qualifier注解值好像也没多大区别吧
你题目里说的情况是假定你在写代码时就已经确定了要使用哪种策略的情况,那么两种写法没什么区别。我提一种情形你看看,比如我要根据不同的客人来决定给他使用什么优惠策略(这是程序运行时动态传入的参数),如果使用接口实现类写法:
@Autowired
private ApplicationContext context;
public double calculateTotalWithDiscount(double orderAmount, String discountStrategyBeanName) {
DiscountStrategy strategy = (DiscountStrategy)context.getBean(discountStrategyBeanName);
OrderContext orderContext = new OrderContext(strategy);
return orderAmount - orderContext.calculateOrderDiscount(orderAmount);
}
如果不使用接口实现类写法:
@Autowired
private ApplicationContext context;
public double calculateTotalWithDiscount(double orderAmount, String discountStrategyBeanName) {
if(discountStrategyBeanName.equals("A策略")){
实现类A aService = context.getBean(实现类A);
return orderAmount - aService.calculateOrderDiscount(orderAmount);//这里方法名可能还不一样
}else if(discountStrategyBeanName.equals("B策略")){
实现类B bService = context.getBean(实现类B)
return orderAmount - bService.calculateOrderDiscount(orderAmount);//这里方法名可能还不一样
}else if(discountStrategyBeanName.equals("C策略")){
实现类C cService = context.getBean(实现类C);
return orderAmount - cService.calculateOrderDiscount(orderAmount);//这里方法名可能还不一样
}//...以后每次新增一个实现类都得在这里加一段
}
当然两种都可以使用,那么以后每多一种策略呢?使用接口的话你需要做的只是写一个实现了接口的类就行了,其他什么都不需要改,不使用接口的话就要多写一个类和多加一种处理,策略多起来以后很容易遗忘也麻烦。另外我觉得还有一个好处是在IDE中可以通过点击某个接口快速找到相关的实现类,这样你就能很快知道有哪些类是处理相关业务的。如果你不涉及我说的情形我觉得倒也没什么区别,无非是美观度和写代码的时间多那么一点点(可能维护也是)。总之你觉得怎么写方便怎么维护容易你就怎么写。
回复

适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容