1、定义
模板方法设计模式(Template Method Design Pattern)是一种行为型设计模式,它定义了一个操作中的算法的骨架,而且将一些步骤延迟到子类中。它使得子类可以改变算法的某些特定步骤,而同时还不改变该算法的结构。具体地说,模板方法定义了一个算法的高层结构,而将具体实现交给子类去完成。
模板方法设计模式包含以下几个角色:
- 抽象类(Abstract Class):定义了一个模板方法,它给出了算法的基本骨架,其中包含若干个步骤,这些步骤的具体实现由子类去完成。
- 具体实现子类(Concrete Class):实现抽象类中的抽象方法,在抽象类中完成的步骤中填入不同的具体实现,以完成算法的不同变体。
2、实现
在实际的应用中,模板方法设计模式常用于将一些公共的算法步骤提取出来,避免代码冗余和耦合性过高,同时也可以灵活地组合和拓展算法的不同实现。
下面是一个简单的模板方法设计模式示例代码:
public abstract class AbstractClass {
/* 模板方法 */
public final void templateMethod() {
method1();
method2();
method3();
}
/* 抽象方法1 */
public abstract void method1();
/* 抽象方法2 */
public abstract void method2();
/* 具体方法3 */
public void method3() {
System.out.println("AbstractClass.method3() is called.");
}
}
public class ConcreteClass extends AbstractClass {
/* 实现抽象方法1 */
@Override
public void method1() {
System.out.println("ConcreteClass.method1() is called.");
}
/* 实现抽象方法2 */
@Override
public void method2() {
System.out.println("ConcreteClass.method2() is called.");
}
}
public class Client {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();
}
}
在上面的示例代码中,AbstractClass为抽象类,定义了一个模板方法templateMethod(),其中包含三个步骤方法:method1()、method2()、method3()。其中method3()为具体方法,而method1()和method2()则为抽象方法,需要具体实现类去完成。
ConcreteClass为具体实现子类,实现了抽象类中的method1()和method2()方法,在抽象类中完成的步骤中填入了具体的实现。
在Client的main方法中,先创建了ConcreteClass对象,再通过该对象调用AbstractClass中定义的模板方法templateMethod(),从而完成了算法的整个流程。在调用模板方法的过程中,先调用了method1()和method2()两个抽象方法,最后调用了具体方法method3()。
3、应用场景
模板方法设计模式常用于以下情况:
-
算法设计:当多个算法或操作具有相同的基本流程和操作步骤,但其具体实现方式各不相同时,可以将这些相同的基本流程和操作步骤提取到一个模板方法中,然后将具体实现延迟到其子类中去完成。
-
复杂实现:当一个方法或操作具有多个步骤、流程或判断逻辑时,可以将其拆分成多个较小的模块,使用模板方法将这些模块组合起来,让代码更易于理解和维护。
-
框架设计:在框架设计中,通常会定义一些基本的操作流程和约束,而具体的业务逻辑则交由使用者来实现。这时,可以利用模板方法设计模式降低使用者的编码难度。
以下是几个实际应用场景:
- 框架设计中,如使用Spring框架时,可以借助Spring提供的模板方法来减轻编程难度,如JdbcTemplate、JmsTemplate、HibernateTemplate等。
- 在游戏开发中,可以使用模板方法来设计游戏关卡、任务流程和角色AI等系统。
- 在Web开发中,可以使用模板方法来处理请求、响应和控制页面流程和表单验证等系统。
public abstract class AbstractWebController {
/* 模板方法 */
public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 验证表单数据合法性
if (validateFormData(request, response)) {
// 处理请求并返回响应
handleRequest(request, response);
} else {
// 验证失败则重定向到错误页面
response.sendRedirect("/error.jsp");
}
}
/* 验证表单数据的合法性 */
protected abstract boolean validateFormData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
/* 处理请求并返回响应 */
protected abstract void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException;
}
public class ConcreteWebController extends AbstractWebController {
/* 实现表单数据验证 */
@Override
protected boolean validateFormData(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 省略具体实现
return true;
}
/* 处理请求并返回响应 */
@Override
protected void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// 省略具体实现
response.sendRedirect("/success.jsp");
}
}
public class Client {
public static void main(String[] args) {
HttpServletRequest request = null;
HttpServletResponse response = null;
AbstractWebController controller = new ConcreteWebController();
try {
controller.processRequest(request, response);
} catch (IOException | ServletException e) {
e.printStackTrace();
}
}
}
在上面的代码示例中,AbstractWebController为抽象类,定义了一个模板方法processRequest(),其中包含两个步骤方法:validateFormData()和handleRequest()。其中validateFormData()为抽象方法,需要具体实现类去完成。handleRequest()为具体方法,处理请求并返回响应。
ConcreteWebController为具体实现子类,实现了抽象类中的validateFormData()和handleRequest()方法,在抽象类中完成的步骤中填入了具体的实现。
在Client的main方法中,先创建了一个ConcreteWebController对象,再通过该对象调用AbstractWebController中定义的模板方法processRequest(),从而完成了请求处理过程。
在具体实现中,可以根据不同的请求和响应需要进行不同的操作,例如验证表单数据合法性、处理请求并返回响应等。由于模板方法processRequest()中定义的流程是固定的,所以无需重复编写相似的代码,可以提高开发效率和代码复用性。
总结:模板方法设计模式可以将相同算法的不变部分放到抽象类中,而将可变的部分放到子类中,通过约束子类的行为来提高代码的复用性和可扩展性。它是一种行为型设计模式,应用广泛,具有简单易懂、结构清晰和代码可维护性高等优点。