设计模式-模板方法模式(Template Method)

一、模板方法模式概述

1.1 什么是模板方法模式

模板方法模式,也被称为模板模式,是一种行为型设计模式。它在一个抽象类中公开定义了执行其方法的模板,规定了算法的骨架。其主要特点是将一些步骤延迟到子类中,这些子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

这种类型的设计模式主要解决了一些通用的方法在每一个子类都重新写了这一问题,其主要目的是将这些通用算法抽象出来。通过使用模板方法模式,子类可以在不改变算法结构的情况下,重新定义算法中的某些特定步骤。

例如,在建筑行业中,造房子的地基、走线、水管等步骤都是一样的,只有在建筑的后期才会有加壁橱加栅栏等差异。在这种情况下,可以使用模板方法模式来规划和设计建筑流程。另一个例子是西游记中的81难,这就是一个典型的顶层逻辑骨架。

1.2 简单实现模板方法模式

首先,创建一个抽象类AbstractClass,其中包含一个抽象方法templateMethod(),这个方法包含了算法的骨架。然后,创建两个子类ConcreteClassA和ConcreteClassB,分别实现了templateMethod()方法。

// 抽象类
public abstract class AbstractClass {
    // 抽象方法,包含算法的骨架
    public final void templateMethod() {
        step1();
        step2();
        step3();
    }

    // 具体步骤1
    protected abstract void step1();

    // 具体步骤2
    protected abstract void step2();

    // 具体步骤3
    protected abstract void step3();
}

// 子类A
public class ConcreteClassA extends AbstractClass {
    @Override
    protected void step1() {
        System.out.println("子类A执行步骤1");
    }

    @Override
    protected void step2() {
        System.out.println("子类A执行步骤2");
    }

    @Override
    protected void step3() {
        System.out.println("子类A执行步骤3");
    }
}

// 子类B
public class ConcreteClassB extends AbstractClass {
    @Override
    protected void step1() {
        System.out.println("子类B执行步骤1");
    }

    @Override
    protected void step2() {
        System.out.println("子类B执行步骤2");
    }

    @Override
    protected 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 {
    @Override
    public void makeSound() {
        // 具体实现
        System.out.println("汪汪汪");
    }
}

// 定义一个子类,实现抽象类中的模板方法
public class Cat extends Animal {
    @Override
    public 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 {
    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }

    // 覆盖父类的默认实现方法
    @Override
    public 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 {
    // 实现抽象方法
    @Override
    public 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); // 输出:执行算法A
        subClass.templateMethod(-1); // 输出:执行算法B
        subClass.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 {
    @Override
    public 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); // 输出:执行算法A
        subClass.templateMethod(-1); // 输出:执行算法B
    }
}
  • 19
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一碗油泼面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值