🌈hello,你好鸭,我是Ethan,一名不断学习的码农,很高兴你能来阅读。
✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!
🔥个人主页:Ethan Yankang
🔥专栏:史上最强八股文||Java项目
🔥温馨提示:划到文末发现专栏彩蛋 点击这里直接传送
🔥本篇概览:详细讲解了策略模式之综合案例工厂升级版。
目录
2.4.3 代码改造(工厂+策略)
(1)整体思路
改造之后,不在service中写业务逻辑,让service调用工厂,然后通过service传递不同的参数来获取不同的登录策略(登录方式)
(2)具体实现
抽象策略类:UserGranter
/**
* 抽象策略类
*/
public interface UserGranter{
/**
* 获取数据
* @param loginReq 传入的参数
* @return map值
*/
LoginResp login(LoginReq loginReq);
}
具体的策略:AccountGranter、SmsGranter、WeChatGranter
/**
* 策略:账号登录
**/
@Component
public class AccountGranter implements UserGranter{
@Override
public LoginResp login(LoginReq loginReq) {
System.out.println("登录方式为账号登录" + loginReq);
// TODO
// 执行业务操作
return new LoginResp();
}
}
/**
* 策略:短信登录
*/
@Component
public class SmsGranter implements UserGranter{
@Override
public LoginResp login(LoginReq loginReq) {
System.out.println("登录方式为短信登录" + loginReq);
// TODO
// 执行业务操作
return new LoginResp();
}
}
/**
* 策略:微信登录
*/
@Component
public class WeChatGranter implements UserGranter{
@Override
public LoginResp login(LoginReq loginReq) {
System.out.println("登录方式为微信登录" + loginReq);
// TODO
// 执行业务操作
return new LoginResp();
}
}
工程类:UserLoginFactory
/**
* 操作策略的上下文环境类 工具类
* 将策略整合起来 方便管理
*/
@Component
public class UserLoginFactory implements ApplicationContextAware {
private static Map<String, UserGranter> granterPool = new ConcurrentHashMap<>();
@Autowired
private LoginTypeConfig loginTypeConfig;
/**
* 从配置文件中读取策略信息存储到map中
* {
* account:accountGranter,
* sms:smsGranter,
* we_chat:weChatGranter
* }
*
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
loginTypeConfig.getTypes().forEach((k, y) -> {
granterPool.put(k, (UserGranter) applicationContext.getBean(y));
});
}
/**
* 对外提供获取具体策略
*
* @param grantType 用户的登录方式,需要跟配置文件中匹配
* @return 具体策略
*/
public UserGranter getGranter(String grantType) {
UserGranter tokenGranter = granterPool.get(grantType);
return tokenGranter;
}
}
在application.yml文件中新增自定义配置
login:
types:
account: accountGranter
sms: smsGranter
we_chat: weChatGranter
新增读取数据配置类
Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "login")
public class LoginTypeConfig {
private Map<String,String> types;
}
改造service代码
@Service
public class UserService {
@Autowired
private UserLoginFactory factory;
public LoginResp login(LoginReq loginReq){
UserGranter granter = factory.getGranter(loginReq.getType());
if(granter == null){
LoginResp loginResp = new LoginResp();
loginResp.setSuccess(false);
return loginResp;
}
LoginResp loginResp = granter.login(loginReq);
return loginResp;
}
}
大家可以看到我们使用了设计模式之后,业务层的代码就清爽多了,如果后期有新的需求改动,比如加入了QQ登录,我们只需要添加对应的策略就可以,无需再改动业务层代码。
2.4.4 举一反三
其实像这样的需求,在日常开发中非常常见,场景有很多,以下的情景都可以使用工厂模式+策略模式解决比如:
-
订单的支付策略
-
支付宝支付
-
微信支付
-
银行卡支付
-
现金支付
-
-
解析不同类型excel
-
xls格式
-
xlsx格式
-
-
打折促销
-
满300元9折
-
满500元8折
-
满1000元7折
-
-
物流运费阶梯计算
-
5kg以下
-
5kg-10kg
-
10kg-20kg
-
20kg以上
-
一句话总结:只要代码中有冗长的 if-else 或 switch 分支判断都可以采用策略模式优化。
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
热门专栏推荐
🌈🌈计算机科学入门系列 关注走一波💕💕
🌈🌈CSAPP深入理解计算机原理 关注走一波💕💕
🌈🌈微服务项目之黑马头条 关注走一波💕💕
🌈🌈redis深度项目之黑马点评 关注走一波💕💕
🌈🌈Java面试八股文系列专栏 关注走一波💕💕
🌈🌈算法leetcode+剑指offer 关注走一波💕💕
📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!