策略模式(多种登录方式实现)
主要是用于一些业务场景相似但业务处理的操作与返回结果不同的的时候,避免使用大量的if else判断语句,代码臃肿,不利于代码维护,使用策略模式会使代码的业务逻辑变得更加清晰,便于阅读理解
策略模式把对象本身和运算规则区分开来,模式分为三个部分。
- 环境类(Context):用来操作策略的上下文环境,下面将它当成工具类
- 抽象策略类(Strategy):策略的抽象,获取数据方式的抽象
- 具体策略类(ConcreteStrategy):具体的策略实现,每一种获取数据方式的具体实现。
下面我们代码去实现一遍就能很清楚的理解了
一、定义抽象策略接口
List中的<?>参数类型为自己需要返回的类型,具体自己定义
/**
* 抽象策略类
*/
public interface UserGranter{
/**
* 获取数据
* @param str 传入的参数 与前端约定好的登录标识
* ACCOUNT:账号密码,
* WX:微信授权,
* SMS:短信验证
* @return map值
*/
Map<String,List<?>> grant(String str);
}
二、具体策略类
/**
* 具体策略实现类A
* 账号登录 ACCOUNT
*
*/
// 注入到ioc 方便管理
@Component(GRANT_TYPE)
public class AccountGranter implements UserGranter{
static final String GRANT_TYPE = "ACCOUNT";
@Override
public Map<String,List<?>> grant(String str) {
Map<String,List<?>> map = new HashMap<>();
List<?> list = new ArrayList<>();
System.out.println("通过账号方式登录" + str);
// TODO
// 执行业务操作
map.put("result", list);
return map;
}
}
/**
* 策略B SMS
*
*/
@Component(GRANT_TYPE)
public class SmsGranter implements UserGranter{
static final String GRANT_TYPE = "SMS";
@Override
public Map<String,List<?>> grant(String str) {
Map<String,List<?>> map = new HashMap<>();
List<?> list = new ArrayList<>();
System.out.println("通过短信方式登录" + str);
// TODO
// 执行业务操作
map.put("result", list);
return map;
}
}
/**
* 策略C WX
*
*/
@Component(GRANT_TYPE)
public class WeChatGranter implements UserGranter{
static final String GRANT_TYPE = "WX";
@Override
public Map<String,List<?>> grant(String str) {
Map<String,List<?>> map = new HashMap<>();
List<?> list = new ArrayList<>();
System.out.println("通过微信方式登录" + str);
// TODO
// 执行业务操作
map.put("result", list);
return map;
}
}
三、环境类实现
/**
* 操作策略的上下文环境类 工具类
* 将策略整合起来 方便管理
*/
@Component
public class UserGranterBuilder{
private Map<String, UserGranter> granterPool = new ConcurrentHashMap<>();
/**
* 所有策略通过ioc 自动注入放入到map中 方便管理 key为实例化名
*
* 在实例化UserGranterBuilder时,spring ioc会自动会将
* UserGranter所有的实例注入到它的有参构造中来时实现实例化
* 将所有的策略串联起来的 关键所在
*/
public UserGranterBuilder(Map<String, UserGranter> granterPool) {
granterPool.forEach(this.granterPool::put);
}
/**
* 对外提供获取具体策略
* @param grantType具体策略的标识
* @return 具体策略
*/
public UserGranter getGranter(String grantType){
UserGranter tokenGranter = granterPool.get(grantType);
return tokenGranter;
}
}
最后服务端的调用
@RestController
@RequestMapping("/miniapp/loginApp")
public class LoginController {
@Autowired
private UserGranterBuilder tokenGranter;
/**
* 与前端约定好的登录标识
* ACCOUNT:账号密码,
* WX:微信授权,
* SMS:短信验证
*/
@PostMapping("/login")
public Map<String,List<?>> login(String grantType) {
// 找到对应的执行实例
UserGranter granter = tokenGranter.getGranter(grantType);
Map<String,List<?>> grantRes = granter.grant(grantType);
return grantRes;
}
}
以上代码便是实现不同策略模式登录的大体思想(接收前端的可以是一个实体或多个值,再传入到各个策略中方便业务操作)