上一篇文章:在实际项目中使用-策略模式 使用了策略模式优雅地解决了实际需求中登陆方式的多样性。但是登陆策略里我们只是简单地打印了一句话,而实际上应该是这样也就是这样的:
1. 判断参数是否合法、正确
2. 实际的登陆逻辑(校验用户名密码)
3. 生成并保存token(jwt)
这4个步骤我们可以看成是一个整体,也就是一个模板。上述的1、2、4步骤是不变的,而唯一变化的是第三步,那么我们就把第三步定义成抽象方法,让实际的登陆策略去重写它。那么让我们开始coding模版方法模式吧。
1. 创建登陆模板抽象类
public abstract class LoginTemplateAbstract implements LoginStrategy {
/**
* 登陆的模版方法
* 模版方法需要用final修饰,防止子类重写
* 如果模版方法里面的某一步是固定不变的,也需要用final修饰
*/
@Override
public final String login(String type) {
// 1. 判断参数是否正确
// 2. 实际的登陆逻辑
String token = loginActually();
// 3. 生成并保存jwt
// 4. 返回token
}
/**
* 不同的登陆逻辑,需要子类去重写
*/
protected abstract String loginActually();
}
2. 实际的登陆策略去继承LoginTemplateAbstract抽象类,而不是实现LoginStrategy接口了
public class GovernmentLoginStrategy extends LoginTemplateAbstract {
@Override
protected String loginActually() {}
}
我们知道在抽象类里面是使用@Autowire注解是没有用的,那我们需要在LoginTemplateAbstract里面使用spring工厂里面的bean怎么办?我们可以使用hutool工具包下的spring模块:SpringUtil.getBean(xxx.class)即可解决
到此我们就完成了一个简单的模版方法模式。
如果后面有需求说政府登陆需要校验密码错误次数,而企业登陆和用户登陆不需要,那么我们要在模板抽象类里加上一个钩子方法
/**
* 是否需要校验密码错误次数,默认不需要
*/
protected boolean needCheckPasswordWrongTime() {
retrun false;
}
然后改下我们的模板方法
public final String login(String type) {
// 1. 判断参数是否正确
// 2. 校验密码错误次数
if (needCheckPasswordWrongTime()) {}
// 3. 实际的登陆逻辑
String token = loginActually();
// 4. 生成并保存jwt
// 5. 返回token
}
最后政府登陆策略重写下needCheckPasswordWrongTime()方法
public class GovernmentLoginStrategy extends LoginTemplateAbstract {
@Override
protected boolean needCheckPasswordWrongTime() {
return true;
}
}
这样我们的模版方法模式基本就完成了。
是不是很酷!