一、引言
今今今今今今今今今天,小编所编写设计模式已经进入白热化状态了,之前介绍了创建型、结构型一共12种设计模式。
现在升级到行为型设计模式了,skr skr skr ~~~
行为型设计模式一共11种,那么今天就来说模板方法模式,这个模板方法设计模式相对来说还是比较好理解的。
二、模板方法基本介绍
有时候我们在功能开发过程当中,会发现新需求和之前的功能很类似,执行的流程都一样,可能就是其中某一个环节略有不同。但是如果全部重写不仅仅浪费时间(指的就是复制和粘贴哈哈哈哈),代码也太冗余了。
这个时候我们就可以考虑使用模板方法模式。
模板方法模式又叫模板模式,在一个抽象类定义了执行它的方法的模板,它的子类可以按需求重写方法实现,但调用将以抽象类中定义的方式进行。
举个例子,将大象放入冰箱,我们需要打开冰箱,把大象塞进去,再把冰箱关上对不对。其中打开冰箱、关闭冰箱这是公用的方法,因为不管你放什么东西,都需要这两个步骤。只是把大象塞进去需要交给子类去实现,因为冰箱可以放很多不同的东西,放什么由调用者决定。
这个抽象类就定义了这些方法,制定了这一套流程的模板,并且不可以改变,唯一可以改变的就是你要放入什么东西进去。
三、模板方法案例演示
我们就用刚刚说所的:将大象塞入冰箱 这个主题转化为代码演示一下。
这个就是我们的抽象类啦,里面定义了打开冰箱、关闭冰箱,并且还有一个抽象的添加方法,需要交给子类实现。
其中还有一个钩子方法:小时候闲的慌或者手痒痒喜欢没事打开下冰箱感受一下冷气,又关上。这个钩子方法就是干这个事情的,它可以控制是否需要添加。
这里默认是需要放入物品的,如果不想要执行这一步流程则可以重写这个钩子方法。
而在这个storing这个方法里面,定义了放入的整个流程并且是final类型不可被重写。
/**
* @Auther: IT贱男
* @Date: 2019/12/6 10:27
* @Description: 定义存放冰箱的步骤
*/
public abstract class AStoring {
/**
* 存放物品
*/
protected final void storing() {
// 打开冰箱
open();
// 添加物品
if (needAdd()) {
add();
}
// 关闭冰箱
close();
}
/**
* 打开冰箱
*/
final void open() {
System.out.println("打开冰箱........");
}
/**
* 关闭冰箱
*/
final void close() {
System.out.println("关闭冰箱........");
}
/**
* 添加物品,放入什么物品由子类来决定
*/
abstract void add();
/**
* 钩子方法
*
* @return
*/
protected boolean needAdd() {
return true;
}
}
当然需要一个具体的子类来继承这个抽象类,实现这个添加方法。
/**
* @Auther: IT贱男
* @Date: 2019/12/6 10:36
* @Description: 将大象放入冰箱
*/
public class StoringElephant extends AStoring {
@Override
void add() {
System.out.println("把大象放入冰箱......");
}
}
/**
* @Auther: IT贱男
* @Date: 2019/12/6 10:37
* @Description:
*/
public class Client {
public static void main(String[] args) {
AStoring storing = new StoringElephant();
storing.storing();
}
}
打开冰箱........
把大象放入冰箱......
关闭冰箱........
假设现在来需求了,流程还是不变,可是放入的东西不太一样,
这里就能体现代码的代码的复用性,并且流程还是保持不变。 这里还可以使用钩子方法,不想放入就重写返回false。
/**
* @Auther: IT贱男
* @Date: 2019/12/7 16:20
* @Description: 将香蕉放入冰箱
*/
public class StoringBanana extends AStoring {
@Override
void add() {
System.out.println("把香蕉放入冰箱......");
}
@Override
protected boolean needAdd() {
return false;
}
}
三、模板方法模式使用注意细节
每个设计模式有优点就肯定有相对应的缺点,冰箱能够存放的种类太多了,一个物品就需要一个子类来实现,这样就很容易导致类个数的增加,也就是类爆炸的现象。
在使用过程中一般模板方法都需要加上final的关键字,比如说我们这个案例就是storing()这个方法,不允许被子类重写。
那么有优点就很明显了,公用的代码都在一个类中,也就是父类中,统一修改比较方便,同时也最大化了代码的复用性。
使用场景一般就是:当要完成某个过程,该过程要执行一系列相关的步骤,这一系列的步骤基本相同。但只有个别步骤不相同的情况下,通常就考虑使用模板方法。
但要注意类爆炸的问题哟。