模板方法模式是一种行为设计模式,它为算法提供了基础方法,称为模板方法,该方法将其某些步骤推迟到子类中,因此算法结构相同,但某些步骤可以由子类根据上下文重新定义。
模板是指预设格式,例如HTML模板,具有固定的预设格式。类似于模板方法模式,我们有一个称为模板方法的预设结构方法,该方法由步骤组成。此步骤可以是抽象方法,将由其子类实现。
简而言之,可以说,在模板方法模式中,存在定义步骤集的模板方法,并且可以将步骤的实现推迟到子类中。因此,模板方法定义了算法,但可以在子类中定义确切的步骤。
何时使用:
- 当您具有算法的预设格式或步骤但步骤的实现可能会有所不同。
- 如果要避免代码重复,请在基类中实现通用代码,并在子类中实现变体。
结构体:
因此,在上图中,您可以看到我们定义了三个步骤,即工序1,工序2和工序3的模板方法。其中操作1和工序2是抽象步骤,因此它们由ConcreteClass实现。我们在此处实现了工序3。在两种情况下,基类中的操作首先是所有人通用的,其次是该方法的默认实现。 UML图现在将更加清晰。
组件:
抽象类
- 它定义了定义算法结构的模板方法。
- 它还定义了抽象操作,这些抽象操作将由子类实现以定义算法步骤。
具体类
- 它实现超类的抽象操作以执行算法的子类特定步骤,并且在不需要默认行为的情况下也覆盖操作
关于模板方法模式的要点:
- 超级类中的模板方法遵循“ 好莱坞原则 ”:“ 不要给我们打电话,我们给您打电话 ”。 这是指这样的事实:不是从子类中的基类调用方法,而是在超类的模板方法中调用了子类的方法。
- 超级类中的模板方法不应被覆盖,因此应使其最终化
- 自定义钩子 :包含默认实现的方法可能会在其他类中被覆盖,这些方法称为钩子方法。 挂钩方法旨在被覆盖,而具体方法则不可。因此,在这种模式下,我们可以提供挂钩方法。问题是有时很难区分挂钩方法和具体方法。
- 模板方法是代码重用的技术,因为有了它,您可以找出常见的行为并将特定的行为推迟到子类。
例:
让我们举个例子。当您必须从两个数据源(即CSV和数据库)中读取数据时,您必须处理该数据并以CSV文件的形式生成输出。这里涉及三个步骤。
- 从相应的数据源读取数据
- 处理数据
- 将输出写入CSV文件
Java代码:
下面的类包含名为“ parseDataAndGenerateOutput”的模板方法,该方法包括读取数据,处理数据以及写入csv文件的步骤。
1.DataParser.java
package org.arpit.javapostsforlearning;abstract public class DataParser {//Template method//This method defines a generic structure for parsing datapublic void parseDataAndGenerateOutput(){readData();processData();writeData();}//This methods will be implemented by its subclassabstract void readData();abstract void processData();//We have to write output in a CSV file so this step will be same for all subclassespublic void writeData(){System.out.println('Output generated,writing to CSV');}
}
在下面的课程中,该课程实施CSV特定步骤
2.CSVDataParser.java
package org.arpit.javapostsforlearning;public class CSVDataParser extends DataParser {void readData() {System.out.println('Reading data from csv file');}void processData() {System.out.println('Looping through loaded csv file'); }
}
在下面的课程中,数据库的特定步骤在该课程中实现
3.数据库DataParser.java
package org.arpit.javapostsforlearning;public class DatabaseDataParser extends DataParser {void readData() {System.out.println('Reading data from database');}void processData() {System.out.println('Looping through datasets'); }
}
4.TemplateMethodMain.java
package org.arpit.javapostsforlearning;public class TemplateMethodMain {/*** @author arpit mandliya*/public static void main(String[] args) {CSVDataParser csvDataParser=new CSVDataParser();csvDataParser.parseDataAndGenerateOutput();System.out.println('**********************');DatabaseDataParser databaseDataParser=new DatabaseDataParser();databaseDataParser.parseDataAndGenerateOutput();}}
输出:
Reading data from csv file
Looping through loaded csv file
Output generated,writing to CSV
**********************
Reading data from database
Looping through datasets
Output generated,writing to CSV
在Java API中使用:
-
java.io.InputStream
,java.io.OutputStream
,java.io.Reader
和java.io.Writer
所有非抽象方法。 -
java.util.AbstractList
,java.util.AbstractSet
和java.util.AbstractMap
所有非抽象方法。 -
javax.servlet.http.HttpServlet
,默认情况下,所有doXXX()
方法都会向响应发送HTTP 405“不允许使用方法”错误。 您可以随意实现任何一个或任何一个。
源代码: 下载
参考:来自我们的JCG合作伙伴 Arpit Mandliya的Java 模板方法设计模式, 适用于初学者博客的Java框架和设计模式 。
翻译自: https://www.javacodegeeks.com/2013/03/template-method-design-pattern-in-java.html