1. 程式人生 > >採用Java 8中Lambda表示式和預設方法的模板方法模式

採用Java 8中Lambda表示式和預設方法的模板方法模式

原文連結 作者:   Mohamed Sanaulla  譯者: 李璟([email protected])

模板方法模式是“四人幫”(譯者注:Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides)所著《Design Patterns book》一書中所描述的23種設計模式其中的一種,該模式旨在:

“Define the skeleton of an algorithm in an operation, deferring some steps to subclasses.

TemplateMethod lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure”。

即模板方法定義一個演算法的架構,並將某些步驟推遲到子類中實現。模板方法允許子類在不改變演算法架構的情況下,重新定義演算法中某些步驟。

為了以更簡單的術語描述模板方法,考慮這個場景:假設在一個工作流系統中,為了完成任務,有4個任務必須以給定的執行順序執行。在這4個任務中,不同工作流系統的實現可以根據自身情況自定義任務的執行內容。

模板方法可以應用在上述場景中:將工作流系統的4個核心任務封裝到抽象類當中,如果任務可以被自定義,則將可自定義的任務推遲到子類中實現。

程式碼實現:

/** 
 * Abstract Workflow system 
 */
abstract class WorkflowManager2{

    public void doTask1(){

        System.out.println("Doing Task1...");

    }

    public abstract void doTask2();

    public abstract void doTask3();

    public void doTask4(){

        System.out.println("Doing Task4...");

    }

}

/** 
 * One of the extensions of the abstract workflow system 
 */
class WorkflowManager2Impl1 extends WorkflowManager2{

    @Override
    public void doTask2(){

        System.out.println("Doing Task2.1...");

    }

    @Override
    public void doTask3(){

        System.out.println("Doing Task3.1...");

    }

}

/** 
 * Other extension of the abstract workflow system 
 */
class WorkflowManager2Impl2 extends WorkflowManager2{

    @Override
    public void doTask2(){

        System.out.println("Doing Task2.2...");

    }

    @Override
    public void doTask3(){

        System.out.println("Doing Task3.2...");

    }

}

我們來看看工作流系統如何使用:

public class TemplateMethodPattern {

    public static void main(String[] args) {

        initiateWorkFlow(new WorkflowManager2Impl1());

        initiateWorkFlow(new WorkflowManager2Impl2());

    }

    static void initiateWorkFlow(WorkflowManager2 workflowMgr){

        System.out.println("Starting the workflow ... the old way");

        workflowMgr.doTask1();

        workflowMgr.doTask2();

        workflowMgr.doTask3();

        workflowMgr.doTask4();

    }

}

輸出如下所示:

Starting the workflow ... the old way

Doing Task1...

Doing Task2.1...

Doing Task3.1...

Doing Task4...

Starting the workflow ... the old way

Doing Task1...

Doing Task2.2...

Doing Task3.2...

Doing Task4...

目前為止一切順利。但是本篇部落格的主要關注點不是模板方法模式,而是如何利用Java 8的Lambda表示式和預設方法實現模板方法模式。我之前已經說過,介面只有在只聲明瞭一個抽象方法的前提下,才可以使用Lambda表示式。這個規則在本篇的例子中應這樣解釋:WorkflowManager2只能有一個抽象或者說自定義的任務。

如果你仍然對Java 8中的Lambda表示式和預設方法感到疑惑,可以在深入研究之前,花一點時間看一看Lambda表示式預設方法這兩篇文章。

我們可以利用帶有預設方法的介面替代抽象類,所以我們的新工作流系統如下所示:

interface WorkflowManager{

    public default void doTask1(){

        System.out.println("Doing Task1...");

    }

    public void doTask2();

    public default void doTask3(){

        System.out.println("Doing Task3...");

    }

    public default void doTask4(){

        System.out.println("Doing Task4...");

    }

}

現在我們的工作流系統帶有一個可自定義的任務2,我們繼續往下走,利用Lambda表示式處理初始化工作:

public class TemplateMethodPatternLambda {

    public static void main(String[] args) {

       /**     
        * Using lambda expression to create different      
        * implementation of the abstract workflow 
        */
        initiateWorkFlow(()->System.out.println("Doing Task2.1..."));

        initiateWorkFlow(()->System.out.println("Doing Task2.2..."));

        initiateWorkFlow(()->System.out.println("Doing Task2.3..."));

    }

    static void initiateWorkFlow(WorkflowManager workflowMgr){

        System.out.println("Starting the workflow ...");

        workflowMgr.doTask1();

        workflowMgr.doTask2();

        workflowMgr.doTask3();

        workflowMgr.doTask4();

    }

}

這就是一個Lambda表示式應用在模板方法模式中的例子。