事件:小菜和大鸟探讨学习,回忆小时候抄黑板知识点时,容易把题目抄错,说着说着大鸟就引入了模板方法模式
模板方法模式:
1.不用设计模式直接设计(结合事件)
2.用模板方法模式去设计(结合事件)
3.看有什么地方继续改进(结合事件)
4.为模板方式模式做小结
大鸟让小菜设计:一个粗心的学生和一个细心的学生去抄同一份试卷
学生a抄好的试卷:
@Slf4jpublicclassTestPaperA{/***试题1*/publicvoidtestQuestion1(){log.info("哥尔·D·罗杰开启了大航海时代,最后的秘宝叫[],a.超级宝藏b.OnePiecec.永恒黄金d.荣耀之石");log.info("答案:b");}/***试题2*/publicvoidtestQuestion2(){log.info("下面哪一个不是真的D:[],a.蒙奇·D·路飞b.波特卡斯·D·罗杰c.马歇尔·D·蒂奇d.特拉法尔加·D·瓦铁尔·罗");log.info("答案:b");}/***试题3*/publicvoidtestQuestion3(){log.info("本博主磕哪一对cp:[],a.佐罗和香吉士b.香吉士和娜美c.佐罗和罗宾d.乔巴和佐罗");log.info("答案:c");}}学生b抄好的试卷
@Slf4jpublicclassTestPaperB{/***试题1*/publicvoidtestQuestion1(){log.info("哥尔·D·罗杰开启了大航海时代,最后的秘宝叫[],a.永恒钻石b.哇塞c.永恒黄金d.大秘宝");log.info("答案:d");}/***试题2*/publicvoidtestQuestion2(){log.info("下面哪一个不是真的D:[],a.蒙奇·D·罗杰b.波特卡斯·D·艾斯c.马歇尔·D·蒂奇d.特拉法尔加·D·瓦铁尔·罗");log.info("答案:a");}/***试题3*/publicvoidtestQuestion3(){log.info("本博主磕哪一对cp:[],a.佐罗和香吉士b.路飞和娜美c.佐罗和罗宾d.乔巴和佐罗");log.info("答案:b");}}客户端代码:
@Slf4jpublicclassTestPaper{publicstaticvoidmain(String[]args){log.info("学生甲抄的试卷:");TestPaperAstudentA=newTestPaperA();studentA.testQuestion1();studentA.testQuestion2();studentA.testQuestion3();log.info("学生乙抄的试卷:");TestPaperBstudentB=newTestPaperB();studentB.testQuestion1();studentB.testQuestion2();studentB.testQuestion3();}}大鸟:你看现在抄出来的两份试卷大体一致,但有很多细节上的地方不一样,而且非常难以维护,为了防止有人抄错,可以抽象一个父类,让子类继承它,然后公共试题代码写到父类中即可
公共试题部分:
@Slf4jpublicclassTestPaper{/***试题1*/publicvoidtestQuestion1(){log.info("哥尔·D·罗杰开启了大航海时代,最后的秘宝叫[],a.超级宝藏b.OnePiecec.永恒黄金d.荣耀之石");}/***试题2*/publicvoidtestQuestion2(){log.info("下面哪一个不是真的D:[],a.蒙奇·D·路飞b.波特卡斯·D·罗杰c.马歇尔·D·蒂奇d.特拉法尔加·D·瓦铁尔·罗");}/***试题3*/publicvoidtestQuestion3(){log.info("本博主磕哪一对cp:[],a.佐罗和香吉士b.香吉士和娜美c.佐罗和罗宾d.乔巴和佐罗");}}学生a和学生b的答题:
@Slf4jpublicclassTestPaperAextendsTestPaper{/***试题1*/@OverridepublicvoidtestQuestion1(){super.testQuestion1();log.info("答案:b");}/***试题2*/@OverridepublicvoidtestQuestion2(){super.testQuestion2();log.info("答案:b");}/***试题3*/@OverridepublicvoidtestQuestion3(){super.testQuestion3();log.info("答案:b");}}@Slf4jpublicclassTestPaperBextendsTestPaper{/***试题1*/@OverridepublicvoidtestQuestion1(){super.testQuestion1();log.info("答案:b");}/***试题2*/@OverridepublicvoidtestQuestion2(){super.testQuestion2();log.info("答案:b");}/***试题3*/@OverridepublicvoidtestQuestion3(){super.testQuestion3();log.info("答案:c");}}大鸟:虽然这样只填写答案即可,但是这只是初步的泛华,其实除了选项abcd,其他的都是重复的。我们既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复
小菜:那应该怎么做呢?
大鸟:这时就要用到模板方法模式了,当我们要完成在某一细节层次,一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式来处理
试题卷(父类):
@Slf4jpublicabstractclassTestPaper{privateStringanswer;/***试题1*/publicvoidtestQuestion1(){log.info("哥尔·D·罗杰开启了大航海时代,最后的秘宝叫[],a.超级宝藏b.OnePiecec.永恒黄金d.荣耀之石");log.info("答案为:{}",answer1());}publicabstractStringanswer1();/***试题2*/publicvoidtestQuestion2(){log.info("下面哪一个不是真的D:[],a.蒙奇·D·路飞b.波特卡斯·D·罗杰c.马歇尔·D·蒂奇d.特拉法尔加·D·瓦铁尔·罗");log.info("答案为:{}",answer2());}publicabstractStringanswer2();/***试题3*/publicvoidtestQuestion3(){log.info("本博主磕哪一对cp:[],a.佐罗和香吉士b.香吉士和娜美c.佐罗和罗宾d.乔巴和佐罗");log.info("答案为:{}",answer3());}publicabstractStringanswer3();}学生a,b自己答题:
@Slf4jpublicclassTestPaperAextendsTestPaper{/***试题1*/@OverridepublicStringanswer1(){return"b";}/***试题2*/@OverridepublicStringanswer2(){return"b";}/***试题3*/@OverridepublicStringanswer3(){return"c";}}@Slf4jpublicclassTestPaperBextendsTestPaper{/***试题1*/@OverridepublicStringanswer1(){return"b";}/***试题2*/@OverridepublicStringanswer2(){return"b";}/***试题3*/@OverridepublicStringanswer3(){return"d";}}客户端:
@Slf4jpublicclassTestPaperLog{publicstaticvoidmain(String[]args){log.info("学生甲抄的试卷:");//这里将子类改为了父类TestPaper,这里就可以用多态性实现代码的复用了TestPaperstudentA=newTestPaperA();studentA.testQuestion1();studentA.testQuestion2();studentA.testQuestion3();log.info("学生乙抄的试卷:");TestPaperstudentB=newTestPaperB();studentB.testQuestion1();studentB.testQuestion2();studentB.testQuestion3();}}
1.概念:它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法模式可以使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤