Android设计模式系列(4)--SDK源码之模板方法模式

十度 Android 2015年12月01日 收藏

模板方法,和单例模式是我认为GOF的23中最简单的两种模式。
但是我个人对模板方法的经典思想特别推崇,虽然模板方法在大对数情况下并不被推荐使用,但是这种通过父类调用子类的方法,使用继承来改变算法的一部分,是面向对象的一种基本认识。
打比方说父亲有很多理想,就行医救人吧,但是父亲医术不行,只能靠儿子,儿子长大后遵从父亲大志,春风拂面,妙手回春,实现了父亲的理想,儿子做的事情早在出生前就定下来了,是父亲之前久定好的模板。
认识到模板方法的这种思想,父类可以让未知的子类去做它本身可能完成的不好或者根本完成不了的事情,对框架学习大有帮助。
本文以View中的draw方法为例,展开分析。
模板方法,TemplateMethod,光是学习这个模式,就会对你产生长远影响的一个模式。

1.意图
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 
热门词汇:骨架 步骤 结构 延迟到子类 

2.结构 

定义了几个步骤1,2,3等,在模板方法中按照一定的结构顺序执行这些步骤。父类的方法可以有缺省实现,也可以是一个空实现,即所谓的钩子操作。
结合实际情况,我们画出View中draw方法涉及到的几个步骤方法如下:


学习模板方法对于我们了解框架的基类实现,生命周期和流程控制非常有帮助,我觉得是务必要掌握的一个模式。

3.代码

public class View{
    /**
     * 钩子操作,空实现
     */
    protected void onDraw(Canvas canvas) {
    }

    /**
     *钩子操作,空实现
     */
    protected void dispatchDraw(Canvas canvas) {
    }

    //算法骨架
    public void draw(Canvas canvas) {
       if (!verticalEdges && !horizontalEdges) {
            // 步骤1
            if (!dirtyOpaque) onDraw(canvas);

            // 步骤2
            dispatchDraw(canvas);

            // 步骤3
            onDrawScrollBars(canvas);

            return;
        }
    }
    //... ...
}

  我们看看系统组件TextView的实现:

public class TextView{
    @Override
    protected void onDraw(Canvas canvas) {
        //大量自定义实现代码
    }
} 

  如果我们自定义View的话,我们一般也是重写onDraw方法即可:

public class MyView extends View {

	public MyView(Context context) {
		super(context);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
	}

	@Override
	protected void dispatchDraw(Canvas canvas) {
	    super.dispatchDraw(canvas);
	}
	
}

4.效果
(1).模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。
(2).模板方法导致一种方向控制结构,"好莱坞法则":"Don't call me,i will call you.",即一个父类调用子类的操作,而不是相反。
(3).模板调用操作的类型有具体的操作,具体的AbstracClass操作,原语操作,工厂方法,钩子操作。少定义原语操作。
(4).android中对这些重定义操作的命名喜欢在方法前加一个前缀on。
(5).模板方法使用继承来改变算法的一部分。策略模式使用委托来改变整个算法。