好久没有写关于设计模式的文章啦,关于这个板块的文章我会不定期的更新,哈哈,很任性! 那今天呢我们要讲到的就是模板方法模式
讲这个模式并不是出于例外,而是对之前知识的一个回顾,可能之前在学习Sevlet或者Spring的时候呢,大家都接触了模板方法模式,只是不知道它叫这个名字而已,没有学习过的朋友呢也不用说现在就去看框架的文章,那是看不懂滴,跟着我们的文章走,还是很容易就可以懂得~
模板方法模式Template Method又称之为钩子方法模式,我们先来举个栗子 话说小李子(莱昂纳多)在18岁那年非常相当一名演员,然后向好莱坞投了简历,这小伙子年轻的时候长得特帅,演技也不错,好莱坞面试管通知它来面试,在试镜得时候也表现得非常不错,随后面试官通知他回去坐等结果,果不其然,过了两天之后就收到好莱坞得信件,通知他被录用啦,在19岁那年,小李子凭借《不一样的天空》里出色的演技获奥斯卡最佳男配提名了!
好我们来看看这个整个过程,不管是谁,想进入好莱坞必须要经过下面几个阶段 可以看出,投简历,试镜,以及最后收到结果都是固定得,但是唯独只有最后通知的方式,或者说结果是不固定得,并且在这个阶段中,小李子是无法直接去询问HR有没有通过,而只能是等待HR得通知,那么我们可以这么来看,投简历是一个方法,试镜是一个方法,收到通知是一个方法,都是固定不变得,主要是看HR最终执行得是什么通知方法,是电话通知呢?还是以正式得录用通知函来告知呢?
基本得框架是不变得,而调用具体哪个方法是可变的可控得,也就是说其中某个节点得方法暂时还不能确定,因此类似于这种情况呢,我们通常采用工厂方法模式,将这个节点得代码得实现转移给子类。可能理论难懂,那我们结合代码来看看吧~
我们定义了一个抽象类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()方法之后,优先会去调用子类重写之后的方法,这么说大家是不是能够明白模板方法模式的使用方式了呢?