一、什么是模板模式
模板模式(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,开启事务等;
期望通过我的讲解,能让大家在实际工作中,一旦遇到类似情况,能够快速使用『模板模式』来重构代码。
网友评论