Android源码学习之模板方法模式应用

一、模板方法模式定义

模板方法模式定义:
defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
定义一个方法操作算法的框架(骨架结构),而将一些步骤延迟到子类中。模板方法使子类可以在不改变一个算法的结构的情况下,就可以重定义该算法的某些特定步骤。

  如上图所示(截取自《Head First Design Patterns》一书),具体各个部分有什么作用见上图,这里就不啰嗦了。

二、模板方法模式优势

封装不变部分,扩展可变部分。把不变部分的算法封装到父类实现,而可变部分的根据子类的具体需要,则可以通过继承来扩展。

提取公共部分,构成一个“模板”,模板的作用在于对算法或者流程的一个结构化、规范化,子类不能修改“模板方法”的整个算法骨架或者流程的顺序等,只能根据自身的不同,对模板方法中算法的某一步进行扩展。

行为由父类控制,子类实现。子类可以通过扩展的方法增加相应的功能,符合开闭原则。

三、模板方法模式在Android源码中的应用

  在Android源码中,View中的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)
         */

具体函数代码如下所示:

View Code

其中第三步( Step 3)Draw view's content函数:

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

第四步( Step 4) draw children  

复制代码
    /**
     * 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) { }
复制代码

  从上面的Draw()“模板方法”可以看出,当继承View子类中,如果要重写或者扩展这个方法时,整个方法流程和基本内容不能够修改,子类只能通过扩展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)两个函数,使子类自己的View显示效果和别的具体子类的不同。现在来看看继承自View类的具体子类如何扩展Draw()模板方法显示自己的与众不同:

  1、TextView类中重写了OnDraw函数

复制代码
@Override
    protected void onDraw(Canvas canvas) { if (mPreDrawState == PREDRAW_DONE) { final ViewTreeObserver observer = getViewTreeObserver(); observer.removeOnPreDrawListener(this); mPreDrawState = PREDRAW_NOT_REGISTERED; } if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return; restartMarqueeIfNeeded(); // Draw the background for this view super.onDraw(canvas); final int compoundPaddingLeft = getCompoundPaddingLeft(); final int compoundPaddingTop = getCompoundPaddingTop(); final int compoundPaddingRight = getCompoundPaddingRight(); final int compoundPaddingBottom = getCompoundPaddingBottom(); final int scrollX = mScrollX; final int scrollY = mScrollY; final int right = mRight; final int left = mLeft; final int bottom = mBottom; final int top = mTop; final Drawables dr = mDrawables; if (dr != null) { /* * Compound, not extended, because the icon is not clipped * if the text height is smaller. 。。。 }
复制代码

  2、SurfaceView重写了dispatchDraw()函数:

复制代码
    @Override
    protected void dispatchDraw(Canvas canvas) { if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { // if SKIP_DRAW is cleared, draw() has already punched a hole if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { // punch a whole in the view-hierarchy below us canvas.drawColor(0, PorterDuff.Mode.CLEAR); } } super.dispatchDraw(canvas); }
复制代码

  3、ViewGroup类重写了dispatchDraw()函数:

复制代码
 @Override
    protected void dispatchDraw(Canvas canvas) { final int count = mChildrenCount; final View[] children = mChildren; int flags = mGroupFlags; if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) { final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE; final boolean buildCache = !isHardwareAccelerated(); for (int i = 0; i < count; i++) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { final LayoutParams params = child.getLayoutParams(); attachLayoutAnimationParameters(child, params, i, count); bindLayoutAnimation(child); if (cache) { child.setDrawingCacheEnabled(true); if (buildCache) { child.buildDrawingCache(true); } } } } final LayoutAnimationController controller = mLayoutAnimationController; if (controller.willOverlap()) { mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE; } controller.start(); mGroupFlags &= ~FLAG_RUN_ANIMATION; mGroupFlags &= ~FLAG_ANIMATION_DONE; if (cache) { mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE; } if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值