現在的網際網路上,想必每個網站都有登入功能,拿我們技術人員常逛的技術網站CSDN
、掘金
、部落格園
等為例,它們都有登入功能,而且它們的登入流程都差不多,如果我們把這些網站的登入流程用程式碼模擬出來,該怎麼弄呢?
在模擬流程之前,先來分析這個登入流程,其實不管哪個網站,登入流程都是以下四步:
- 1、跳轉到登入頁面
- 2、輸入使用者名稱和密碼
- 3、點選登入按鈕
- 4、跳轉到首頁
我們就照著這個流程來用程式碼來模擬網站登入的過程,我們以 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:抽象類
- ConcreteClass:具體的實現類
我們用模板方法模式來重新設計我們的模擬登入過程, 我們按照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()
方法就是用模板方法來排序的,有興趣的可以去深入瞭解一下。
最後
打個小廣告,歡迎掃碼關注微信公眾號:「平頭哥的技術博文」,一起進步吧。