现在的互联网上,想必每个网站都有登录功能,拿我们技术人员常逛的技术网站CSDN
、掘金
、博客园
等为例,它们都有登录功能,而且它们的登录流程都差不多,如果我们把这些网站的登录流程用代码模拟出来,该怎么弄呢?
在模拟流程之前,先来分析这个登录流程,其实不管哪个网站,登录流程都是以下四步:
我们就照着这个流程来用代码来模拟网站登录的过程,我们以 CSDN
、掘金
为例。
/**
* 模拟csdn登录
*/
public class CsdnLogin {
// 第一步:获取登录页面
public void getLoginPage(){
System.out.println("跳转到csdn登录页面...");
}
// 第二步:设置用户名密码
public void setUserAndPass(){
System.out.println("设置好了csdn的用户名和密码...");
}
// 第三步:点击登录
public void clickLogin(){
System.out.println("点击了csdn的登录按钮...");
}
// 进入主页
public void home(){
System.out.println("欢迎来到CSDN社区...");
}
}
/**
* 模拟掘金登录
*/
public class JuejinLogin {
// 第一步:获取登录页面
public void getLoginPage(){
System.out.println("跳转到掘金登录页面...");
}
// 第二步:设置用户名密码
public void setUserAndPass(){
System.out.println("设置好了掘金的用户名和密码...");
}
// 第三步:点击登录
public void clickLogin(){
System.out.println("点击了掘金的登录按钮...");
}
// 进入主页
public void home(){
System.out.println("欢迎来到掘金社区...");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("--------模拟登录到csdn--------");
System.out.println("");
CsdnLogin csdn = new CsdnLogin();
csdn.getLoginPage();
csdn.setUserAndPass();
csdn.clickLogin();
csdn.home();
System.out.println("");
System.out.println("--------模拟登录到掘金--------");
System.out.println("");
JuejinLogin juejin = new JuejinLogin();
juejin.getLoginPage();
juejin.setUserAndPass();
juejin.clickLogin();
juejin.home();
}
}
从测试结果来看,我们的设计和实现都没有一点问题,在这里CSDN
、掘金
都有自己的控制流程,那如果我一不小心把juejin.clickLogin();
写到了juejin.setUserAndPass();
的前面,那我的登录岂不是失败了?仔细想想,CSDN
、掘金
登录流程都是一样的,那我们能不能把这个流程固定到一个方法中,让它变成一个不可变的标准流程呢?也许这是可行的,我们使用一种新的设计模式,叫做模板方法模式。先一起来简单了解一下模板方法模式。
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法模式相对其他模式来说比较简单,模板方法模式就涉及到两个角色:
我们用模板方法模式来重新设计我们的模拟登录过程, 我们按照AbstractClass
的规则来实现模拟登录的模板抽象类LoginTemplate
,LoginTemplate
类的具体设计如下:
/**
* 模板方法模式-抽象类
*/
public abstract class LoginTemplate {
abstract void getLoginPage();
abstract void setUserAndPass();
abstract void clickLogin();
abstract void home();
/**
* 在模板中定义了一个运行方法
* 这个方法会按照我么需要的顺序去执行
*/
public final void login(){
getLoginPage();
setUserAndPass();
clickLogin();
home();
System.out.println("");
}
}
我们将登录涉及到的四个方法抽到到这个中,并且定义了一个模板方法login()
,模板方法中的定义好了执行的顺序,需要特别注意的地方是模板方法使用了final
修饰,这样做的目的是防止子类重写改变执行的顺序。
ConcreteClass
类是具体的实现,我们需要定义两个ConcreteClass
类,Csdn
、JueJin
类是我们的具体实现,这两个类的具体实现跟上面的逻辑跟我们最开始设计的差不多,Csdn
、JueJin
类的具体实现如下:
public class Csdn extends LoginTemplate {
@Override
public void getLoginPage() {
System.out.println("跳转到csdn登录页面...");
}
@Override
public void setUserAndPass() {
System.out.println("设置好了csdn的用户名和密码...");
}
@Override
public void clickLogin() {
System.out.println("点击了csdn的登录按钮...");
}
@Override
public void home() {
System.out.println("欢迎来到CSDN社区...");
}
}
public class JueJin extends LoginTemplate {
@Override
public void getLoginPage() {
System.out.println("跳转到掘金登录页面...");
}
@Override
public void setUserAndPass() {
System.out.println("设置好了掘金的用户名和密码...");
}
@Override
public void clickLogin() {
System.out.println("点击了掘金的登录按钮...");
}
@Override
public void home() {
System.out.println("欢迎来到掘金社区...");
}
}
重新编写我们的测试类App
,测试类的具体代码如下:
public class App {
public static void main(String[] args) {
// 模拟csdn登录
LoginTemplate csdn = new Csdn();
// 调用模板方法
csdn.login();
// 模拟掘金登录
LoginTemplate juejin = new JueJin();
juejin.login();
}
}
测试结果:
使用模板方法模式之后,给我们模拟登录带来了哪些好处?我总结了一下,使用模板方法模式带来了如下好处:
LoginTemplate
类主导一切,它有一个保护login()
方法控制着整个登录流程clickLogin()
添加一个verify()
方法,然后子类做具体实现就好,保证了这个流程不会出错。从我们的网站登录案例中,可以看出模板方法模式确实给我们带来了不少的好处,一起来总结一下模板方法模式的优缺点吧。
最后多少一句,JDK 中的Collections.sort()
方法就是用模板方法来排序的,有兴趣的可以去深入了解一下。