1700448342
编写高质量代码:改善Java程序的151个建议 建议108:反射让模板方法模式更强大
1700448343
1700448344
模板方法模式(Template Method Pattern)的定义是:定义一个操作中的算法骨架,将一些步骤延迟到子类中,使子类不改变一个算法的结构即可重定义该算法的某些特定步骤。简单地说,就是父类定义抽象模板作为骨架,其中包括基本方法(是由子类实现的方法,并且在模板方法被调用)和模板方法(实现对基本方法的调度,完成固定的逻辑),它使用了简单的继承和覆写机制,我们来看一个基本的例子。
1700448345
1700448346
我们经常会开发一些测试或演示程序,期望系统在启动时自行初始化,以方便测试或讲解,一般的做法是写一个SQL文件,在系统启动前手动导入,不过,这样不仅麻烦而且还容易出现错误,于是我们就自己动手写了一个初始化数据的框架:在系统(或容器)启动时自行初始化数据。但问题是每个应用程序要初始化的内容我们并不知道,只能由实现者自行编写,那我们就必须给作者预留接口,此时就得考虑使用模板方法模式了,代码如下:
1700448347
1700448348
public abstract class AbsPopulator{
1700448349
1700448350
//模板方法
1700448351
1700448352
public final void dataInitialing()throws Exception{
1700448353
1700448354
//调用基本方法
1700448355
1700448356
doInit();
1700448357
1700448358
}
1700448359
1700448360
//基本方法
1700448361
1700448362
protected abstract void doInit();
1700448363
1700448364
}
1700448365
1700448366
这里定义了一个抽象模板类AbsPopulator,它负责数据初始化,但是具体要初始化哪些数据则是由doInit方法决定的,这是一个抽象方法,子类必须实现,我们来看一个用户表数据的加载:
1700448367
1700448368
public class UserPopulator extends AbsPopulator{
1700448369
1700448370
protected void doInit(){
1700448371
1700448372
/*初始化用户表,如创建、加载数据等*/
1700448373
1700448374
}
1700448375
1700448376
}
1700448377
1700448378
该系统在启动时,查找所有的AbsPopulator实现类,然后dataInitialing实现数据的初始化。那读者可能要想了,怎么让容器知道这个AbsPopulator类呢?很简单,如果是使用Spring作为IoC容器的项目,直接在dataInitialing方法上加上@PostConstruct注解,Spring容器启动完毕后会自动运行dataInitialing方法,由于这里的原理超出了本书的范畴,不再赘述。
1700448379
1700448380
现在的问题是:初始化一张User表需要非常多的操作,比如先建表,然后筛选数据,之后插入,最后校验,如果把这些都放到一个doInit方法里会非常庞大(即使提炼出多个方法承担不同的职责,代码的可读性依然很差),那该如何做呢?又或者doInit是没有任何的业务意义的,是否可以起一个优雅而又动听的名字呢?
1700448381
1700448382
答案是我们可以使用反射增强模板方法模式,使模板方法实现对一批固定规则的基本方法的调用。代码是最好的交流语言,我们看看怎么改造AbsPopulator类,代码如下:
1700448383
1700448384
public abstract class AbsPopulator{
1700448385
1700448386
//模板方法
1700448387
1700448388
public final void dataInitialing()throws Exception{
1700448389
1700448390
//获得所有的public方法
[
上一页 ]
[ :1.700448341e+09 ]
[
下一页 ]