关闭

Android源码中的模板方法模式

标签: android源码设计模式view类族模板方法模式
2175人阅读 评论(0) 收藏 举报
分类:

从装饰者模式到Context类族

当观察者模式和回调机制遇上Android源码

Android源码中的静态工厂方法

Android中的工厂方法模式

Android源码中的命令模式

Android源码中的适配器模式

Android源码中的外观模式

定义

模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。

使用场景

  1. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。

  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。

  3. 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

结构

模式所涉及的角色有:

  • 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。

  • 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。

模板方法中的方法可以分为两大类:模板方法和基本方法。

  • 模板方法

    一个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。

    一个抽象类可以有任意多个模板方法,而不限于一个。每一个模板方法都可以调用任意多个具体方法。

  • 基本方法

    基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。

    • 抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。

    • 具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。

    • 钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。

实现

分析完理论,我们用一个饮料店出售饮料的小例子来分析一下模板方法模式。夏天我们去饮料店购买饮料,告诉服务员要一大杯奶茶,还要加冰

那么饮料店是如何装配我们的饮料的呢?首先准备一个大杯子,然后入我们需要的饮料,如果加冰会放入一些冰块,最后盖好盖子打包给我们。

仔细思考一下我们的使用场景,有没有发现很符合呢?接下来我们用代码实现一下。

抽象方法,装配饮料的模板

/**
 * 饮料模板
 * Created by lei on 2016/10/19.
 */

public abstract class TemplateDrink {

    /**
     * 获取饮料的方法,用final修饰,防止被子类修改算法结构。模板方法
     */
    public final void getDrink() {
        getGlass();
        getContent();
        if (hook()) {
            Log.e(TAG, "加冰--->");
        } else {
            Log.e(TAG, "不加冰--->");
        }
        pack();
    }

    /**
     * 获取杯子,杯子分大中小杯
     */
    public abstract void getGlass();

    /**
     * 获取具体种类饮料
     */
    public abstract void getContent();

    /**
     * 夏天我们的饮料是默认加冰的。钩子方法
     */
    public boolean hook() {
        return true;
    }

    /**
     * 打包
     */
    public void pack() {
        Log.e(TAG, "包装");
    }
}

这里需要注意的是getDrink()方法是用final修饰的,这样就保证了逻辑流程不会被子类修改,子类只能修改某一个步骤的具体实现。

具体某种饮料的实现

/**
 * 具体的饮料,比如奶茶
 * Created by lei on 2016/10/19.
 */

public class ConcreteDrink extends TemplateDrink {

    @Override
    public void getGlass() {
        Log.e(TAG, "中杯--->");
    }

    @Override
    public void getContent() {
        Log.e(TAG, "奶茶--->");
    }

    @Override
    public boolean hook() {
        return super.hook();
    }
}

Android源码中的模板方法模式

这个模式相对来说比较简单,但是应用却非常广泛,毕竟越简单越容易应用嘛。比如在重构的时候,把相同的代码抽取到父类中,然后配合钩子函数约束其行为。

当然在Android源码中的应用肯定也不少,比如AsyncTask的实现,调用execute后会依次执行onPreExecute、doInBackground、onPostExecute,还可以通过onProgressUpdate来更新进度,它的执行过程其实是一个框架,类似的还有Activity的生命周期回调方法的执行。

接下来我们看一个比较明显的,即View中的Draw()方法

我们先看下方法注释

/**
* Manually render this view (and all of its children) to the given Canvas.
* The view must have already done a full layout before this function is
* called. When implementing a view, implement
* {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
* If you do need to override this method, call the superclass version.
*
* @param canvas The Canvas to which the View is rendered.
*/

在我们调用layout()方法之后,可以调用draw()方法来手动渲染view(包括它的子view)到传入的canvas上。如果我们继承View类的话需要重写ondraw()方法而不是draw()。如果你必须重写,需要调用超类的版本。

draw()方法比较长,我们挑主要的看一下。

方法开头有一段注释是这样的:

/*
* Draw traversal performs several drawing steps which must be executed
* in the appropriate order:
*
* 1. Draw the background
* 2. If necessary, save the canvas’ layers to prepare for fading
* 3. Draw view’s content
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
*/

遍历执行几个绘制步骤,并且这些步骤需要按适当顺序执行。

我们重点看下3和4

// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);

// Step 4, draw the children
dispatchDraw(canvas);

具体方法如下

/**
 * Implement this to do your drawing.
 *
 * @param canvas the canvas on which the background will be drawn
 */
protected void onDraw(Canvas canvas) {
}

/**
 * Called by draw to draw the child views. This may be overridden
 * by derived classes to gain control just before its children are drawn
 * (but after its own view has been drawn).
 * @param canvas the canvas on which to draw the view
 */
protected void dispatchDraw(Canvas canvas) {

}

我们看一下View类族的UML图

这里写图片描述

子类只能通过扩展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)两个函数,使子类的显示效果和别的具体子类。

接下来对号入座,draw()对应我们的模板方法,ondraw()和dispatchDraw()就是钩子方法。

搞定,收工。

测试代码已上传到github

1
0
查看评论

Android源码分析之模板方法模式

Android源码分析之模板方法模式,Android中AsyncTask的模板方法设计模式
  • bboyfeiyu
  • bboyfeiyu
  • 2014-08-14 18:19
  • 3669

Android中的模板方法模式

定义:定义一个方法操作算法的框架(骨架结构),而将一些步骤延迟到子类中。模板方法使子类可以在不改变一个算法的结构的情况下,就可以重定义该算法的某些特定步骤。就像一个工厂车间的流水线一样,每一步其实都是可以固定的,就是具体的内容有些区别,这样就可以定义一个大致的流程框架,子类就直接按照这个框架来就可以...
  • hp910315
  • hp910315
  • 2016-03-12 21:43
  • 976

TemplateMethod模板方法模式之应用

一,定义:模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。            二,类图:       ...
  • liujiahan629629
  • liujiahan629629
  • 2014-02-22 19:37
  • 2358

【设计模式】——原型模式VS模板方法模式

不知道何种原因总是把原型模式和模板方法模式搞混,着实很苦恼啊!不知道大家是否有同样的困扰,有的话治疗,没有的话预防啊。故该文章进行详细对比学习! 原型模式     所谓的原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。     解释:...
  • jiadajing267
  • jiadajing267
  • 2015-11-02 19:47
  • 1016

行为型模式之模板方法模式(java版)

1.引入 模板方法模式就是当我们需要把某些细节层次,但器个别步骤的更详细的实现却是不同的时候,就需要用模板方法模式。实际上就是把一些更详细的信息在子类中去实现,这里更详细的信息就是可变的信息,因为每个子类都不同,所以具有可变信息,然后把不变的行为给他封装到父类中去,这样就去除子类中重复的代码了。 2...
  • ya_1249463314
  • ya_1249463314
  • 2016-08-26 10:43
  • 362

图形学优化_3: 观察者模式和模板方法模式

定义对象间的依赖关系,当一个对象的状态发生变化时,所有依赖他的对象都得到通知 OGRE的各种消息:更新,键盘,鼠标 消息的发布:责任链关系定义一个算法的骨架,而将一些步骤延迟到子类中。 模板子类可以不改变一个算法的结构就可以重新定义该算法的某些特定的步骤。
  • mijian1207mijian
  • mijian1207mijian
  • 2015-12-21 20:38
  • 177

设计模式——Spring IoC中用到的模板方法模式

http://www.cnblogs.com/gnidoc/p/4981447.html 基本概念 什么是模板方法(Template method):父类定义了骨架(调用哪些方法及顺序),某些特定方法由子类实现。 最大的好处:代码复用,减少重复代码。除了子类要实现的特定方法,其...
  • z69183787
  • z69183787
  • 2017-03-24 10:55
  • 1614

模板方法模式例子

原文地址:http://www.cnblogs.com/jenkinschan/p/5768760.html一、概述 模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。二、结构类图三、解决问题模板方法就是提供...
  • disiwei1012
  • disiwei1012
  • 2016-12-05 17:14
  • 892

【java设计模式】之 模板方法(Template Method)模式

1. 模板方法的一个实例         这一节主要来学习一下设计模式中的模板方法模式。我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验设...
  • eson_15
  • eson_15
  • 2016-05-06 08:57
  • 4050

IOS 设计模式 模板模式

转载:http://my.oschina.net/daguoshi/blog/486734?p={{totalPage}} 模板方法模式是面向对象软件设计中一种非常简单的设计模式。其基本思想是:定义一个操作中算法的骨架,而将一些步骤延迟到到子类中。模板方法使子类可以重定义算法的某些特定步骤而不改...
  • lcg910978041
  • lcg910978041
  • 2016-04-24 15:55
  • 233
    个人资料
    • 访问:197901次
    • 积分:2259
    • 等级:
    • 排名:第19598名
    • 原创:40篇
    • 转载:0篇
    • 译文:3篇
    • 评论:105条
    我的微信公众号
    长期为您推荐优秀博文、开源项目、视频等,进入还有好玩的等着你。扫一扫下方二维码或搜索微信号codertopia即可关注:
    我的

    QQ群:469291650


    GitHub
    我的个人博客
    博客专栏
    Relax
    最新评论