设计模式-模板方法模式(Template Method)
设计模式-模板方法模式(Template Method)
- 一、模板方法模式概述
- 1.1 什么是模板方法模式
- 1.2 简单实现模板方法模式
- 1.3 使用模板方法模式的注意事项
- 二、模板方法模式的用途
- 三、模板方法模式实现方式
- 3.1 抽象类中定义模板方法,子类实现具体方法。
- 3.2 抽象类中定义模板方法,子类实现部分方法,父类提供默认实现。
- 3.3 抽象类中定义多个模板方法,每个模板方法对应不同的算法流程。
- 3.4 抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程。
一、模板方法模式概述
1.1 什么是模板方法模式
模板方法模式,也被称为模板模式,是一种行为型设计模式。它在一个抽象类中公开定义了执行其方法的模板,规定了算法的骨架。其主要特点是将一些步骤延迟到子类中,这些子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
这种类型的设计模式主要解决了一些通用的方法在每一个子类都重新写了这一问题,其主要目的是将这些通用算法抽象出来。通过使用模板方法模式,子类可以在不改变算法结构的情况下,重新定义算法中的某些特定步骤。
例如,在建筑行业中,造房子的地基、走线、水管等步骤都是一样的,只有在建筑的后期才会有加壁橱加栅栏等差异。在这种情况下,可以使用模板方法模式来规划和设计建筑流程。另一个例子是西游记中的81难,这就是一个典型的顶层逻辑骨架。
1.2 简单实现模板方法模式
首先,创建一个抽象类AbstractClass,其中包含一个抽象方法templateMethod(),这个方法包含了算法的骨架。然后,创建两个子类ConcreteClassA和ConcreteClassB,分别实现了templateMethod()方法。
// 抽象类
public abstract class AbstractClass {// 抽象方法,包含算法的骨架public final void templateMethod() {step1();step2();step3();}// 具体步骤1protected abstract void step1();// 具体步骤2protected abstract void step2();// 具体步骤3protected abstract void step3();
}// 子类A
public class ConcreteClassA extends AbstractClass {@Overrideprotected void step1() {System.out.println("子类A执行步骤1");}@Overrideprotected void step2() {System.out.println("子类A执行步骤2");}@Overrideprotected void step3() {System.out.println("子类A执行步骤3");}
}// 子类B
public class ConcreteClassB extends AbstractClass {@Overrideprotected void step1() {System.out.println("子类B执行步骤1");}@Overrideprotected void step2() {System.out.println("子类B执行步骤2");}@Overrideprotected void step3() {System.out.println("子类B执行步骤3");}
}
最后,在客户端代码中,可以创建不同的子类对象,并调用它们的templateMethod()方法来执行算法
public class Client {public static void main(String[] args) {AbstractClass concreteClassA = new ConcreteClassA();concreteClassA.templateMethod();AbstractClass concreteClassB = new ConcreteClassB();concreteClassB.templateMethod();}
}
运行客户端代码,可以看到输出结果如下:
子类A执行步骤1
子类A执行步骤2
子类A执行步骤3
子类B执行步骤1
子类B执行步骤2
子类B执行步骤3
1.3 使用模板方法模式的注意事项
-
1、抽象类应该定义算法的骨架,将一些步骤延迟到子类中实现。这些步骤应该是通用的,可以被不同的子类重写。
-
2、抽象类中的抽象方法需要声明为final,防止被子类修改。
-
3、抽象类可以包含一些具体的方法,这些方法可以在子类中被覆盖或直接调用。
-
4、子类需要实现抽象类中的所有抽象方法,否则子类也必须声明为抽象类。
-
5、客户端代码应该针对抽象类进行编程,而不是针对具体的子类。这样可以提高代码的可扩展性和可维护性。
-
6、在模板方法模式中,子类可以根据需要对算法的某些特定步骤进行修改,但是整个算法的结构不应该被改变。
-
7、模板方法模式适用于那些算法结构相对稳定,但某些步骤需要根据具体情况进行变化的场景。如果算法结构经常发生变化,那么使用策略模式可能更加合适。
二、模板方法模式的用途
模板方法模式,也被称为模板模式(Template Pattern),是一种行为型设计模式。它在一个抽象类中公开定义了执行其方法的模板,规定了算法的骨架。其主要特点是将一些步骤延迟到子类中实现,这些步骤可以是通用的,可以被不同的子类重写。
在Java编程语言中,模板方法模式被广泛应用。例如,在Servlet中,有一种叫做"processRequest"的方法,这个方法就是一个模板方法,定义了一系列的流程,如获取请求参数、调用service方法处理业务逻辑、返回响应结果等。具体的业务逻辑处理则由子类去实现。
此外,模板方法模式还常用于创建复杂的对象。比如在创建一个复杂的汽车对象时,这个汽车有很多部件和功能,有些部件和功能的创建和装配过程是相似的,而有些则是独特的。在这种情况下,就可以使用模板方法模式来定义一个汽车对象的创建和装配过程的骨架,然后让子类去实现具体的创建和装配过程。
总的来说,模板方法模式的优点在于提高代码复用性,增加扩展性,并且符合开闭原则。
三、模板方法模式实现方式
3.1 抽象类中定义模板方法,子类实现具体方法。
这是最常见的实现方式,也是最简单的实现方式。
// 定义一个抽象类
public abstract class Animal {// 定义一个模板方法public void makeSound() {// 默认实现System.out.println("动物发出声音");}
}// 定义一个子类,实现抽象类中的模板方法
public class Dog extends Animal {@Overridepublic void makeSound() {// 具体实现System.out.println("汪汪汪");}
}// 定义一个子类,实现抽象类中的模板方法
public class Cat extends Animal {@Overridepublic void makeSound() {// 具体实现System.out.println("喵喵喵");}
}// 测试代码
public class Main {public static void main(String[] args) {Animal dog = new Dog();dog.makeSound(); // 输出:汪汪汪Animal cat = new Cat();cat.makeSound(); // 输出:喵喵喵}
}
3.2 抽象类中定义模板方法,子类实现部分方法,父类提供默认实现。
这种方式可以使得子类更加灵活,可以根据需要选择是否覆盖父类的方法。
要实现抽象类中定义模板方法,子类实现部分方法,父类提供默认实现,可以按照以下步骤进行:
创建一个抽象类,包含一个抽象方法作为模板方法。
在抽象类中定义一个或多个默认实现的方法。
创建子类,继承抽象类,并实现抽象方法。
在子类中覆盖父类的默认实现方法。
以下是一个简单的示例:
// 抽象类
public abstract class Animal {// 模板方法public void makeSound() {System.out.println("动物发出声音");}// 默认实现方法public void eat() {System.out.println("动物吃东西");}
}// 子类
public class Dog extends Animal {// 实现抽象方法@Overridepublic void makeSound() {System.out.println("汪汪汪");}// 覆盖父类的默认实现方法@Overridepublic void eat() {System.out.println("狗狗吃骨头");}
}// 测试代码
public class Main {public static void main(String[] args) {Animal dog = new Dog();dog.makeSound(); // 输出:汪汪汪dog.eat(); // 输出:狗狗吃骨头}
}
3.3 抽象类中定义多个模板方法,每个模板方法对应不同的算法流程。
这种方式适用于有多种算法流程的场景,可以提高代码的可读性和可维护性。
要实现抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程,可以按照以下步骤进行:
- 1、创建一个抽象类,包含一个带有参数的抽象方法作为模板方法。
- 2、在抽象类中定义一个或多个默认实现的方法。
- 3、创建子类,继承抽象类,并实现抽象方法。
- 4、在子类的实现方法中,根据传入的参数选择不同的算法流程。
以下是一个简单的示例:
// 抽象类
public abstract class AbstractClass {// 带参数的抽象方法作为模板方法public abstract void templateMethod(int param);// 默认实现的方法public void defaultMethod() {System.out.println("这是默认实现的方法");}
}// 子类
public class SubClass extends AbstractClass {// 实现抽象方法@Overridepublic void templateMethod(int param) {if (param > 0) {algorithmA();} else {algorithmB();}}// 根据参数选择不同的算法流程private void algorithmA() {System.out.println("执行算法A");}private void algorithmB() {System.out.println("执行算法B");}
}// 测试代码
public class Main {public static void main(String[] args) {SubClass subClass = new SubClass();subClass.templateMethod(1); // 输出:执行算法AsubClass.templateMethod(-1); // 输出:执行算法BsubClass.defaultMethod(); // 输出:这是默认实现的方法}
}
3.4 抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程。
这种方式适用于算法流程比较复杂的场景,可以提高代码的灵活性和扩展性。
要实现抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程,可以按照以下步骤进行:
- 1、创建一个抽象类,包含一个带有参数的抽象方法作为模板方法。
- 2、在抽象类中定义一个或多个默认实现的方法。
- 3、创建子类,继承抽象类,并实现抽象方法。
- 4、在子类的实现方法中,根据传入的参数选择不同的算法流程。
以下是一个简单的示例:
// 抽象类
public abstract class AbstractClass {// 带参数的抽象方法作为模板方法public abstract void templateMethod(int param);// 默认实现的方法protected void defaultMethod() {System.out.println("这是默认实现的方法");}
}// 子类
public class SubClass extends AbstractClass {@Overridepublic void templateMethod(int param) {if (param > 0) {algorithmA();} else {algorithmB();}}private void algorithmA() {System.out.println("执行算法A");}private void algorithmB() {System.out.println("执行算法B");}
}// 测试代码
public class Main {public static void main(String[] args) {SubClass subClass = new SubClass();subClass.templateMethod(1); // 输出:执行算法AsubClass.templateMethod(-1); // 输出:执行算法B}
}