概述
概论
什么是模板模式呢?模板模式是这么定义的:定义一个操作中的算法的框架,而将这个框架中的某一些步骤延迟到子类中。使得子类可以不改变一个算法的结构。而能够重新定义该算法的某一些特定的步骤。
模板模式示例
举个例子,假如我们工作中的系统需要和许多的外部系统做交互时。由于外部系统各种各样,因此我们在发起请求时,处理方式会有所不多,有些是http请求,有些的webservice请求。或者是其他请求。然而真正在做的应该分成4个步骤。
1.参数校验。
2.封装对外的请求参数。
3.对外提交请求。
4.后置处理,例如记录操作日志。
ok,首先我们需要拥有一个抽象模板类用来定义这些步骤。
1 packagecom.example.pattern.template;2
3 public abstract classAbstractProccessor {4
5 public booleanvalidate(ExampleContext context) {6 if (context == null) {7 return false;8 }9
10 return true;11 }12
13 public abstract voidprepare(ExampleContext context);14
15 public abstract voidproccess(ExampleContext context);16
17 public abstract voidafter(ExampleContext context);18
19
20
21 public voidrun (ExampleContext context) {22
23 validate(context);24
25 prepare(context);26
27 proccess(context);28
29 after(context);30
31 }32
33 }
抽象模板类AbstractProccessor 对外提供一个算法,也就是run方法。 这个算法中包含了参数校验,前置处理,提交请求,后置处理4个步骤。由于参数校验是最基本也是最公共的校验,因此在这个抽象模板中直接实现参数校验的具体方法。其他三个方法就以抽象方法的形态存在。
现在我们新增一个具体的模板类。比如我们就叫HttpProccessor。
1 packagecom.example.pattern.template;2
3 public class HttpProccessor extendsAbstractProccessor {4
5 @Override6 public voidprepare(ExampleContext context) {7
8 System.out.println("http 前置处理");9
10 }11
12 @Override13 public voidproccess(ExampleContext context) {14
15 System.out.println("http 提交请求");16
17 }18
19 @Override20 public voidafter(ExampleContext context) {21
22 System.out.println("http 后置处理");23
24 }25 }
我们继续新增一个模板类,命名为OtherProccessor。
1 packagecom.example.pattern.template;2
3 public class OtherProccessor extendsAbstractProccessor {4
5 @Override6 public voidprepare(ExampleContext context) {7
8 System.out.println("other 前置处理");9
10 }11
12 @Override13 public voidproccess(ExampleContext context) {14
15 System.out.println("other 提交请求");16
17 }18
19 @Override20 public voidafter(ExampleContext context) {21
22 System.out.println("other 后置处理");23
24 }25 }
最后我们提供一个业务场景类Client
packagecom.example.pattern.template;public classClient {public static voidmain(String[] args) {
AbstractProccessor proccessor= newHttpProccessor();
proccessor.run(newExampleContext());
}
}
执行结果如下所示:
1 http 前置处理2 http 提交请求3 http 后置处理
模板方法的精髓在于定义一个算法,这个算法中包含一系列的步骤,这些步骤如果是公共的步骤,可以提取在抽象模板类中实现,如果是模板个性化的行为,可以延迟到子类去实现。
现在再提出一个问题。我想在有些模板中不使用后置处理,有些模板中使用后置处理,也就是要不要后置处理,交给业务场景来确定,那该怎么办呢?我们在抽象模板类中增加一个方法标记是否需要后置处理。
1 packagecom.example.pattern.template;2
3 public abstract classAbstractProccessor {4
5 public booleanvalidate(ExampleContext context) {6 if (context == null) {7 return false;8 }9
10 return true;11 }12
13 public abstract voidprepare(ExampleContext context);14
15 public abstract voidproccess(ExampleContext context);16
17 public abstract voidafter(ExampleContext context);18
19 protected boolean needAfterProccessing () {20 return true;21 }22
23
24
25 public voidrun (ExampleContext context) {26
27 validate(context);28
29 prepare(context);30
31 proccess(context);32
33 if(needAfterProccessing()) {34 after(context);35 }36 }37
38 }
needAfterProccessing方法子类可以实现重写。代码如下所示:
1 packagecom.example.pattern.template;2
3 public class HttpProccessor extendsAbstractProccessor {4
5 protected boolean needAfterProccessing = false;6
7 @Override8 public voidprepare(ExampleContext context) {9
10 System.out.println("http 前置处理");11
12 }13
14 @Override15 public voidproccess(ExampleContext context) {16
17 System.out.println("http 提交请求");18
19 }20
21 @Override22 public voidafter(ExampleContext context) {23
24 System.out.println("http 后置处理");25
26 }27
28
29 @Override30 protected booleanneedAfterProccessing() {31 returnneedAfterProccessing;32 }33
34
35 public booleanisNeedAfterProccessing() {36 returnneedAfterProccessing;37 }38
39 public void setNeedAfterProccessing(booleanneedAfterProccessing) {40 this.needAfterProccessing =needAfterProccessing;41 }42 }
我们再来修改一下客户端,设置不需要进行后置处理:
1 packagecom.example.pattern.template;2
3 public classClient {4
5 public static voidmain(String[] args) {6
7 AbstractProccessor proccessor = newHttpProccessor();8
9 ((HttpProccessor) proccessor).setNeedAfterProccessing(false);10
11 proccessor.run(newExampleContext());12
13
14 }15 }
运行结果如下所示:
1 http 前置处理2 http 提交请求
通过以上的方式,我们采用把相同的代码(都要进行判断是不是需要后置处理)这个判断的抽象动作封装在抽象类中,而在子类再去约束他具体的行为,这个函数就叫作钩子函数。
模板模式的优点
1.封装不变部分,扩展可变部分。
2.提取公共部分。
3.引入了钩子函数,行为由父类控制,子类实现。
模板模式的缺点
抽象类在一般情况下的作用是用来定义抽象行为,而模板模式却是将算法的处理步骤实现在抽象类中,抽象类中定义了抽象方法,交给子类去实现,而子类的实现方式会影响到父类的算法。在代码阅读上对技术有一定的要求。
模板模式的使用场景
1.多个子类有共有的方法,同时基本的处理逻辑相同。
2.重要复杂的算法,可以把算法设计成模板模式,算法中的变化的步骤定义为抽象步骤。
3.重构时,把相同或者相似的代码提取到抽象类中,并且使用钩子函数来约束父类的算法。
一般对于Java的开发者而言,对HttpServlet都很熟悉。Servlet使用来浏览器和tomcat服务器沟通的桥梁,而这个桥梁的简单封装就是HttpServlet。每一次的请求都会去调用service方法,而service方法中根据请求的参数,调用不同的方法。例如doGet或者doPost。而doGet或者doPost都是在子类中定义定位,因此这两个函数也叫作钩子函数,即子类改变父类的行为。这也是对设计模式,模板模式的最佳应用。
最后
以上就是英俊水池为你收集整理的java 模板参数_Java设计模式之模板模式的全部内容,希望文章能够帮你解决java 模板参数_Java设计模式之模板模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复