if-else
假设现在要开发一个邮件服务,要对接所有的邮件服务提供厂商,那么代码可能是这样的:
public class MailHandle {
public void send(String providerName, String msg) {
// 如果要发到 qq邮箱
if ("qq".equals(providerName)) {
sendMsgToQQ(msg);
}
// 如果要发到网易邮箱
else if ("ntes".equals(providerName)) {
sendMsgToNtes(msg);
}
// 如果要发到阿里云邮箱
else if ("alibaba".equals(providerName)) {
sendMsgToAlibaba(msg);
}
}
}
Oh,My God!这简直是灾难,让我们用策略模式让代码更加具备扩展性吧。
设计思想
Context: 对策略进行封装,对外暴露统一的方法send()。
Strategy: 策略接口,定义抽象方法。
implStrategy: 图中的QQ,NTES,Alibaba都是Strategy的实现类。实现具体的业务方法。
代码实现
- MailStrategyService
public interface MailStrategyService {
/**
* 服务提供商名称
*
* @return
*/
public String getServiceProviderName();
/**
* 发送邮件
*
* @param message
*/
public void send(String message);
}
- NASDAQMailStrategyServiceImpl
@Service
@Slf4j
public class NASDAQMailStrategyServiceImpl implements MailStrategyService {
@Override
public String getServiceProviderName() {
return "ntes";
}
@Override
public void send(String message) {
log.info("现在向网易邮箱发送邮件:{}",message);
}
}
- QQMailStrategyServiceImpl
@Service
@Slf4j
public class QQMailStrategyServiceImpl implements MailStrategyService {
@Override
public String getServiceProviderName() {
return "qq";
}
@Override
public void send(String message) {
log.info("向QQ邮箱发送邮件:{}",message);
}
}
- MailStrategyContext
@Component
@Slf4j
@Getter
public class MailStrategyContext {
/**
* 策略
* KEY为业务编码
* VALUE为具体实现类
*/
private final ConcurrentHashMap<String, MailStrategyService> strategy = new ConcurrentHashMap<>();
/**
* 注入所有实现 MailStrategyService 接口的类
* 这里使用的是构造注入的方式将Bean注入进来
*
* @param mailServiceList
*/
public MailStrategyContext(List<MailStrategyService> mailServiceList) {
log.info("开始注入策略");
mailServiceList.forEach(mailServiceImpl -> {
log.info("当前策略类:{}", mailServiceImpl.getClass().getName());
strategy.put(mailServiceImpl.getServiceProviderName(), mailServiceImpl);
});
log.info("注入策略完毕");
}
/**
* 发送邮件
*
* @param strategyName 策略名称
* @param message 发送邮件信息
*/
public void send(String strategyName, String message) {
MailStrategyService mailStrategyService = strategy.get(strategyName);
mailStrategyService.send(message);
}
}
- StrategyController
@RestController
@RequestMapping("/mail")
public class StrategyController {
@Autowired
private MailStrategyContext mailStrategy;
@PostMapping("/{bussinessCode}/send")
public void sendMail(@PathVariable(value = "bussinessCode") String bussinessCode,
@RequestParam(value = "message") String message) {
mailStrategy.send(bussinessCode, message);
}
}
- 使用PostMan测试
-
发到QQ邮箱
-
发到网易邮箱
if-else,Goodbye!