模板方法模式,從網站登入開始說起

平頭哥的技術博文發表於2019-09-25

現在的網際網路上,想必每個網站都有登入功能,拿我們技術人員常逛的技術網站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的規則來實現模擬登入的模板抽象類LoginTemplateLoginTemplate類的具體設計如下:

/**
 * 模板方法模式-抽象類
 */
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類,CsdnJueJin類是我們的具體實現,這兩個類的具體實現跟上面的邏輯跟我們最開始設計的差不多,CsdnJueJin類的具體實現如下:

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()方法就是用模板方法來排序的,有興趣的可以去深入瞭解一下。

最後

打個小廣告,歡迎掃碼關注微信公眾號:「平頭哥的技術博文」,一起進步吧。

平頭哥的技術博文

相關文章