常见设计模式之模板模式
1、什么是模板模式
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按照需要重写方法实现,但调用将以抽象类中定义的方式进行,这种类型的设计模式属于行为模式
2、介绍
- 应用场景:做一件事情的方法有很多,但做这件事的步骤都可以归纳为几步,这个时候就可以用模板模式。
- 作用:在模板类中定义做事的步骤,将多种实现做事的细节在子类中实现。即:定义一个操作中的算法的骨架(模板函数),而将一些步骤延迟到子类中(基本函数)。模板模式使得子类可以不改变一个算法的结构(模板函数),即可重定义该算法的实现方式(基本函数)。
- 应用实例:AQS(AbstractQueuedSynchronizer)就是基于模板模式来实现,提供一种实现阻塞锁和一系列依赖FIFO等待队列的同步器的框架,AQS模板为ReentedLocK、CountDownLatch、Semaphore提供了优秀的解决方案。
- 优点:1、封装不变部分,扩展可变部分 2、提取公共代码,便于维护 3、行为父类控制,子类实现
- 缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
3、实现
在这里描述一个场景,用户去银行办理业务的流程(排队取号 -> 到柜台办理业务 -> 给业务员打分)。但是不同的用户去办理的业务有可能不一样,比如张三去存钱,李四去取钱,王五去办卡……
基于这种场景下,就可以使用模板模式,先创建一个抽象类,定义流程中的几个步骤,代码如下:
@Slf4j
abstract class AbstractBankService {
/**
* 1、排队取号
*
* @param name 姓名
* @return true or false
*/
protected Boolean queueUp(String name) {
log.info("用户{}排队取号", name);
return true;
}
/**
* 2、到柜台办理业务
*
* @param name 姓名
*/
protected void handleBusiness(String name) {
log.info("用户{}办理业务", name);
}
/**
* 3、为服务打分
*
* @param name 姓名
*/
protected void score(String name) {
log.info("用户{}为服务打分", name);
}
/**
* 银行业务流程
*
* @param name 姓名
*/
public final void bankBusiness(String name) {
log.info("用户{}进入银行", name);
if (this.queueUp(name)) {
this.handleBusiness(name);
}
this.score(name);
log.info("用户{}离开银行", name);
}
}
注:抽象类中的方法 queueUp()、handleBusiness()、score() 都是对应上面提到的基本函数,基本函数是可拓展的;bankBusiness() 对应模板函数,模板函数是不可变的,需要用 final 修饰
然后可以根据具体业务去创建不同的类去继承这个抽象类,然后重写父类方法实现具体业务逻辑,代码如下:
@Slf4j
public class TransferService extends AbstractBankService {
@Override
protected void handleBusiness(String name) {
log.info("用户{}办理转账业务", name);
}
public void service(String name) {
bankBusiness(name);
}
public static void main(String[] args) {
TransferService transferService = new TransferService();
transferService.service("xiaohu");
}
}
执行 TransferService 的 main 方法,打印结果如下:
22:20:07.554 [main] INFO cn.enjoyedu.springboot.es.highlevel.designMode.template.AbstractBankService - 用户:xiaohu进入银行
22:20:07.560 [main] INFO cn.enjoyedu.springboot.es.highlevel.designMode.template.AbstractBankService - 用户:xiaohu排队取号
22:20:07.560 [main] INFO cn.enjoyedu.springboot.es.highlevel.designMode.template.TransferService - 用户:xiaohu办理转账业务
22:20:07.560 [main] INFO cn.enjoyedu.springboot.es.highlevel.designMode.template.AbstractBankService - 用户:xiaohu为服务打分
22:20:07.561 [main] INFO cn.enjoyedu.springboot.es.highlevel.designMode.template.AbstractBankService - 用户:xiaohu离开银行