Android设计模式—模板方法模式

1.模板方法模式

模板方法模式是一种行为型设计模式。它定义一个算法骨架,而将一些步骤延迟到子类中,即在父类中编排主流程,将步骤实现延迟到子类去实现。模板方法使得子类可以在不改变算法的结构下,重定义该算法的某些特定步骤。

此模式总结概括就是流程封装,也就是把某个固定的流程封装到一个final方法中,并且让子类能够定制这个流程中的某些或所有步骤,这就要求父类提取公用的代码,提升代码的复用率,同时带来了更好的可扩展性。

 

UML类图:

9d13742b58b04036b270273965033e3f.png

抽象父类AbstractClass:实现了模板方法,定义了一套算法框架。

具体实现类ConcreteClass1、ConcreteClass2:实现抽象类中的抽象方法,即不同的对象的具体实现细节。

 

使用场景:

①算法的整体步骤很固定,但其中个别部分易变时,可使用模板方法模式将容易变化的部分抽象出来,供子类去实现。

②当多个子类有公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。

当需要控制子类的扩展时,模板方法模式在特定点调用钩子方法,使用钩子方法让子类决定父类的某个步骤是否执行,实现子类对父类的反向控制。

②重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。

③重构时,模板方法模式是一个经常使用的模式,把相同的代码抽到父类中,然后通过子类约束其行为。

 

模板方法模式优点:

①提高代码复用性,将相同部分的代码放在抽象的父类中,而不同的代码放入不同的子类中。

②实现了反向控制一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制,符合开闭原则。

缺点:

①每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

 

2.模板方法模式的实现

抽象模板:

public abstract class AbstractTemplate {

    //模板方法

    public void templateMethod() {

        doOperation1();

        if(isNeedOperation2) {

            doOperation2();

        }

        doOperation3();

    }

    // 基本方法--抽象方法

    protected abstract void doOperation1();

    // 基本方法

    protected void doOperation2() {

        // 空实现,子类实现

    }

    // 基本方法-具体方法由抽象类声明并实现,而子类并不实现或置换

    protected void doOperation3() {

        // 业务逻辑省略..

    }

    //钩子方法,是否需要第二步,默认需要

    protected boolean isNeedOperation2(){

        return true; //使用钩子方法让子类决定父类的某个步骤是否执行,实现子类对父类的反向控制

    }

}

具体模板:

public class ConcreteTemplateA extends AbstractTemplate {

    @Override

    protected void doOperation1() {

        // 业务逻辑省略..

    }

    @Override

    protected void doOperation2() {

        // 业务逻辑省略..

    }

    protected boolean isNeedOperation2(){

        return true; 

    }

}

public class ConcreteTemplateB extends AbstractTemplate {

    @Override

    protected void doOperation1() {

        // 业务逻辑省略..

    }

    @Override

    protected void doOperation2() {

        // 业务逻辑省略..

    }

    protected boolean isNeedOperation2(){

        return false; //该子类的算法不需要第二步

    }

}

客户端:

ConcreteTemplateA aa = new ConcreteTemplateA();

ConcreteTemplateB bb = new ConcreteTemplateB();

aa.templateMethod();

bb.templateMethod();

 

在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来设置布局。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值