1.模板方法模式
模板方法模式属于行为型模式。是指定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
此模式总结概括就是流程封装,也就是把某个固定的流程封装到一个final方法中,并且让子类能够定制这个流程中的某些或者所有步骤,这就要求父类提取公用的代码,提升代码的复用率,同时带来了更好的可扩展性。
UML类图:
AbstractClass:抽象类,定义了一套算法框架。
ConcreteClass1:具体实现类1。
ConcreteClass2:具体实现类2。
使用场景:
①多个子类有公共的方法,并且逻辑基本相同。使用钩子方法让子类决定父类的某个步骤是否执行,实现子类对父类的反向控制。
②重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
③重构时,模板方法模式是一个经常使用的模式,把相同的代码抽到父类中,然后通过子类约束其行为。
模板方法模式优点:
①提高代码复用性,将相同部分的代码放在抽象的父类中,而不同的代码放入不同的子类中。
②实现了反向控制一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制,符合开闭原则。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
2.模板方法模式的实现
在Android开发中,每一个activity都会有很多相同的方法,例如:初始化界面、初始化数据、设置相同的主题等。这时候就可以使用模板方法模式来优化。
①新建一个BaseActivity基类,在里面定义算法框架:
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
//模板方法,多个基本方法的组合
public final void firstInit{
setContentView(initLayout());
initView();
if(isInitData()) { //钩子方法
initData();
}
}
//基本方法,模板方法里面调用
protected abstract int initLayout();
protected abstract void initData();
protected abstract void initView();
//钩子方法,是否需要初始化数据,默认为 true
protected boolean isInitData() {
return true;
}
}
把setContentView()方法放在了父类中,在每一个子类传入布局id就可以了。
定义了一个钩子方法,当默认需要初始化数据时,什么都不用改动;如果不需要初始化数据,只需要覆写钩子方法isInitData并返回false即可。
②子类
public class TestActivity extends BaseActivity {
@Override
protected int initLayout() {
return R.layout.activity_test;
}
@Override
protected void initView() {
//本activity的findViewById()等操作
}
@Override
protected void initData() {
//本activity的初始化数据
}
}
模板方法实际上是封装一个固定流程,就像一套固定模板一样,第一步该做什么,第二步该做什么都已经在抽象类中定义好。而子类可以有不同的算法实现,在框架不被修改的情况下实现某些步骤的算法替换。
注意:
1)父类中的基本方法尽量设计为protected,符合迪米特原则。
2)父类中的模板方法一般设置为final,不允许子类重写。目的一是为了避免子类恶意操作,二是为了模板的共性。
3.Android源码中的模板方法模式
①AsyncTask
在使用AsyncTask时,把耗时操作放到doInBackground(Params… params)中,在doInBackground之前,如果想做一些初始化操作,可以把实现写在onPreExecute中,当doInBackground执行完后会执行onPostExecute方法,而我们只需要构建AsyncTask对象,然后执行execute方法。
②Activity的生命周期
ActivityThread的main函数被调用后,依次执行Activity的onCreate、onStart、onResume函数,用户通常在Activity的子类中覆写onCreate方法,并且在该方法中调用setContentView来设置布局。