java 模板参数_Java设计模式之模板模式

概论

什么是模板模式呢?模板模式是这么定义的:定义一个操作中的算法的框架,而将这个框架中的某一些步骤延迟到子类中。使得子类可以不改变一个算法的结构。而能够重新定义该算法的某一些特定的步骤。

模板模式示例

举个例子,假如我们工作中的系统需要和许多的外部系统做交互时。由于外部系统各种各样,因此我们在发起请求时,处理方式会有所不多,有些是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都是在子类中定义定位,因此这两个函数也叫作钩子函数,即子类改变父类的行为。这也是对设计模式,模板模式的最佳应用。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值