在实际项目中使用-模版方法模式

1,046 阅读2分钟

上一篇文章:在实际项目中使用-策略模式 使用了策略模式优雅地解决了实际需求中登陆方式的多样性。但是登陆策略里我们只是简单地打印了一句话,而实际上应该是这样也就是这样的:

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;
    }
}

这样我们的模版方法模式基本就完成了。

是不是很酷!