Marco's Java【设计模式】之【模板方法模式】

前言

好久没有写关于设计模式的文章啦,关于这个板块的文章我会不定期的更新,哈哈,很任性!
那今天呢我们要讲到的就是模板方法模式

什么是模板方法模式

讲这个模式并不是出于例外,而是对之前知识的一个回顾,可能之前在学习Sevlet或者Spring的时候呢,大家都接触了模板方法模式,只是不知道它叫这个名字而已,没有学习过的朋友呢也不用说现在就去看框架的文章,那是看不懂滴,跟着我们的文章走,还是很容易就可以懂得~

模板方法模式Template Method又称之为钩子方法模式,我们先来举个栗子
话说小李子(莱昂纳多)在18岁那年非常相当一名演员,然后向好莱坞投了简历,这小伙子年轻的时候长得特帅,演技也不错,好莱坞面试管通知它来面试,在试镜得时候也表现得非常不错,随后面试官通知他回去坐等结果,果不其然,过了两天之后就收到好莱坞得信件,通知他被录用啦,在19岁那年,小李子凭借《不一样的天空》里出色的演技获奥斯卡最佳男配提名了!

好我们来看看这个整个过程,不管是谁,想进入好莱坞必须要经过下面几个阶段
在这里插入图片描述
可以看出,投简历,试镜,以及最后收到结果都是固定得,但是唯独只有最后通知的方式,或者说结果是不固定得,并且在这个阶段中,小李子是无法直接去询问HR有没有通过,而只能是等待HR得通知,那么我们可以这么来看,投简历是一个方法,试镜是一个方法,收到通知是一个方法,都是固定不变得,主要是看HR最终执行得是什么通知方法,是电话通知呢?还是以正式得录用通知函来告知呢?

基本得框架是不变得,而调用具体哪个方法是可变的可控得,也就是说其中某个节点得方法暂时还不能确定,因此类似于这种情况呢,我们通常采用工厂方法模式,将这个节点得代码得实现转移给子类。可能理论难懂,那我们结合代码来看看吧~

模板方法模式示例
package com.marco.template;

public abstract class HollywoodInterview {
	
	public void receiveResumes() {
		System.out.println("HR收到简历");
	}
	public void callForInterview() {
		System.out.println("HR发出面试通知并试镜");
	}
	
	public abstract void evaluate();
	
	public void sendResult(String name) {
		System.out.println("发送面试结果给" + name);
	}
	
	public final void interview(String name) {
		receiveResumes();
		callForInterview();
		evaluate();
		sendResult(name);
	}
}

class PassInterview extends HollywoodInterview {

	@Override
	public void evaluate() {
		System.out.println("过来上班");
	}
}

class FailInterview extends HollywoodInterview {

	@Override
	public void evaluate() {
		System.out.println("试试别家吧");
	}
}

我们定义了一个抽象类HollywoodInterview,然后由它的子类去实现它得抽象方法,注意了,这里的interview()方法我是用final写死了得,意在不让子类去重写父类得方法,接下来我们安排小李子去面试

public class Artists {
	public static void main(String[] args) {
		HollywoodInterview interview = new PassInterview();
		interview.interview("小李子");
	}
}

在这里插入图片描述
不过,我们通常会使用匿名内部类的方式去实现接口并直接调用它的方法,效果也是一摸一样的

package com.marco.template;

public class Artists {
	public static void main(String[] args) {
		HollywoodInterview interview = new HollywoodInterview() {
			@Override
			public void evaluate() {
				System.out.println("过来上班");
			}
		}; 
		interview.interview("小李子");
	}
}

通过上面得栗子,我们发现,我们得父类将整个流程体系规定得死死得,然后由子类重写它的抽象方法,通过这种方式起到一个约束和规范得作用,并且当我们调用interview()方法得时候我们发现,它像一个"钩子"一样,我只管调用evalute()方法,当我执行得时候,挂到哪一个子类得方法上就调用哪个子类重写之后的方法,反观,子类是无法重写并修改父类得interview()方法。

因此,这就是为什么我们也称他为"钩子"方法得原因,他还有一个好记得别名,叫
“好莱坞原则:Don’t call me, we’ll call you back”

艺人只能够把简历递给娱乐公司,试镜之后,只能被动得等待安排,需要你的时候我就传呼你,不需要你的时候,你爱干啥干啥,与我无瓜~

使用模板方法得场景

那说了半天,什么时候该使用模板方法呢?
其实根据上面得简单得栗子不难发现,父类有几个步骤是固定不变得,能变动得就只有抽象方法了,因此,当我们实现一个算法,整体得步骤很固定,但是某些地方很容易变动时,那么这一部分我们可以单独抽离出来为一部分,通过子类重写父类抽象方法得方式,实现方法得运转。

在实际开发中,也有很多地方使用到了模板方法模式,例如我们得

  • 数据库访问封装
  • Servlet关于doPost、doGet方法得调用
  • Hibernate模板程序
  • spring-JDBCTemplate等等

学习过前面得Servelt,对于doPost、doGet是再熟悉不过了,我们通过子类继承父类HttpServlet的方式,重写它的doGet()和doPost()方法,而service()就好比那个模板,当页面的请求过来的时候,优先会调用service()方法,然后会判断具体是以什么方式请求,来决定调用哪种方法,其实我们向上追溯到HttpServlet的父类GenericServlet时会发现,这个service()方法就是一个抽象方法
在这里插入图片描述
当子类重写了doGet()和doPost()方法之后,优先会去调用子类重写之后的方法,这么说大家是不是能够明白模板方法模式的使用方式了呢?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值