模板方法模式是“*”(译者注: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个核心任务封装到抽象类当中,如果任务可以被自定义,则将可自定义的任务推迟到子类中实现。
代码实现:
02 |
* Abstract Workflow system
|
04 |
abstract class WorkflowManager2{
|
06 |
public void doTask1(){
|
08 |
System.out.println( "Doing Task1..." );
|
12 |
public abstract void doTask2();
|
14 |
public abstract void doTask3();
|
16 |
public void doTask4(){
|
18 |
System.out.println( "Doing Task4..." );
|
25 |
* One of the extensions of the abstract workflow system
|
27 |
class WorkflowManager2Impl1 extends WorkflowManager2{
|
30 |
public void doTask2(){
|
32 |
System.out.println( "Doing Task2.1..." );
|
37 |
public void doTask3(){
|
39 |
System.out.println( "Doing Task3.1..." );
|
46 |
* Other extension of the abstract workflow system
|
48 |
class WorkflowManager2Impl2 extends WorkflowManager2{
|
51 |
public void doTask2(){
|
53 |
System.out.println( "Doing Task2.2..." );
|
58 |
public void doTask3(){
|
60 |
System.out.println( "Doing Task3.2..." );
|
我们来看看工作流系统如何使用:
01 |
public class TemplateMethodPattern {
|
03 |
public static void main(String[] args) {
|
05 |
initiateWorkFlow( new WorkflowManager2Impl1());
|
07 |
initiateWorkFlow( new WorkflowManager2Impl2());
|
11 |
static void initiateWorkFlow(WorkflowManager2 workflowMgr){
|
13 |
System.out.println( "Starting the workflow ... the old way" );
|
15 |
workflowMgr.doTask1();
|
17 |
workflowMgr.doTask2();
|
19 |
workflowMgr.doTask3();
|
21 |
workflowMgr.doTask4();
|
输出如下所示:
01 |
Starting the workflow ... the old way |
11 |
Starting the workflow ... the old way |
目前为止一切顺利。但是本篇博客的主要关注点不是模板方法模式,而是如何利用Java 8的Lambda表达式和默认方法实现模板方法模式。我之前已经说过,接口只有在只声明了一个抽象方法的前提下,才可以使用Lambda表达式。这个规则在本篇的例子中应这样解释:WorkflowManager2只能有一个抽象或者说自定义的任务。
如果你仍然对Java 8中的Lambda表达式和默认方法感到疑惑,可以在深入研究之前,花一点时间看一看Lambda表达式和默认方法这两篇文章。
我们可以利用带有默认方法的接口替代抽象类,所以我们的新工作流系统如下所示:
01 |
interface WorkflowManager{
|
03 |
public default void doTask1(){
|
05 |
System.out.println( "Doing Task1..." );
|
09 |
public void doTask2();
|
11 |
public default void doTask3(){
|
13 |
System.out.println( "Doing Task3..." );
|
17 |
public default void doTask4(){
|
19 |
System.out.println( "Doing Task4..." );
|
现在我们的工作流系统带有一个可自定义的任务2,我们继续往下走,利用Lambda表达式处理初始化工作:
01 |
public class TemplateMethodPatternLambda {
|
03 |
public static void main(String[] args) {
|
06 |
* Using lambda expression to create different
|
07 |
* implementation of the abstract workflow
|
09 |
initiateWorkFlow(()->System.out.println( "Doing Task2.1..." ));
|
11 |
initiateWorkFlow(()->System.out.println( "Doing Task2.2..." ));
|
13 |
initiateWorkFlow(()->System.out.println( "Doing Task2.3..." ));
|
17 |
static void initiateWorkFlow(WorkflowManager workflowMgr){
|
19 |
System.out.println( "Starting the workflow ..." );
|
21 |
workflowMgr.doTask1();
|
23 |
workflowMgr.doTask2();
|
25 |
workflowMgr.doTask3();
|
27 |
workflowMgr.doTask4();
|
这就是一个Lambda表达式应用在模板方法模式中的例子。