Java设计模式(二):模板模式(Template Pattern)

600 阅读2分钟

一、什么是模板模式

模板模式(Template Pattern),一个抽象类定义一个固定流程,流程中的某些方法,需要子类去实现;模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤。这种类型的设计模式属于行为型模式。

二、解决了什么问题

一些类似功能的类,其流程或算法相同,只是个别功能不同,而使得流程或算法最终的结果不一致;我们把这些类的功能和流程抽象到一个父类中,然后,只定义子类需要实现差异功能即可;这样,能极大的简化子类的开发。

三、实现

模式模式至少需要两个类:

  • 抽象类(Abstract class):定义并实现整个流程或算法,流程中的各别功能抽象出来由子类实现(可选);
  • 具象类(Concrete class):继承模板抽象类,并重载部分或全部方法(抽象类会限定哪些方法可以被重载);

3.1、定义抽象类及流程

我们定义一个『Ball』抽象类,并给出了必需实现和可选实现的方法:

abstract public class Ball {
    public final void run() {
        System.out.println("do something");
        start();

        if (whichBody() == 0) {
            useFeet();
        } else {
            useHand();
        }

        end();
        System.out.println("finished");
    }

    // 定义了子类必需实现的方法
    abstract void start();
    abstract int whichBody();
    abstract void end();
    
    // 定义了子类可选择性重载的方法
    protected void useHand() {
        throw new UnsupportedOperationException();
    }
    protected void useFeet() {
        throw new UnsupportedOperationException();
    }
}

3.2、定义两个子类:『BasketBall』 和『FootBall』

我们知道,篮球是用手来投球的,而足球是用脚来踢球的,所以,篮球类需要实现可选方法:useHand;同理,足球类需要实现可选方法:useFeet;

// 篮球
public class BasketBall extends Ball {
    @Override
    void start() {
        System.out.println("BasketBall -----> start");
    }

    @Override
    int whichBody() {
        return 1;
    }

    @Override
    protected void useHand() {
        System.out.println("BasketBall -----> use hand");
    }

    @Override
    void end() {
        System.out.println("BasketBall -----> end");
    }
}
// 足球
public class FootBall extends Ball {
    @Override
    void start() {
        System.out.println("FootBall -----> start");
    }

    @Override
    int whichBody() {
        return 0;
    }

    @Override
    protected void useFeet() {
        System.out.println("FootBall -----> use feet");
    }

    @Override
    void end() {
        System.out.println("FootBall -----> end");
    }
}

3.3、测试

public class Main {
    public static void main(String[] args) {
        Ball ball = new BasketBall();
        ball.run();

        System.out.println("---------- 模板模式 ----------");

        ball = new FootBall();
        ball.run();
    }
}

// 打印输出结果:
// do something
// BasketBall -----> start
// BasketBall -----> use hand
// BasketBall -----> end
// finished
// ---------- 模板模式 ----------
// do something
// FootBall -----> start
// FootBall -----> use feet
// FootBall -----> end
// finished

四、应用场景

大家平常可能会经常遇到,也会偶尔代码重构并抽象一套公共流程给到子类使用,只是大家并不一定其实它是一种设计模式。

在实际中,应用的场景很多:

  • JDK中的 AbstractQueuedSynchronizer (抽象队列同步器)及其一系列子类实现的不同功能的锁;
  • Spring 对 JDBC 的支持:获取 Session、关闭 Session,开启事务等;

期望通过我的讲解,能让大家在实际工作中,一旦遇到类似情况,能够快速使用『模板模式』来重构代码。