Android設計模式--模板方法模式
到國美面試Android的時候,問我的設計模式相關的問題:
1、單例模式的意義時什麼;
2、有哪幾種Factory 方法模式;
3、你用過的模板方法模式,舉例說明;
自己感覺答的一塌糊塗。模板方法模式都沒說出來;
悲劇!
基礎不牢,地動山搖。
大公司注重基礎,所以對於java 基礎,設計模式,演算法。這些是一定牢固的!
1、定義:
定義一個操作演算法的骨架,將一些步驟延伸到子類中。
模版方法模式使得子類可以不改變演算法結構即可重定義該演算法的某些步驟。
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.
2、作用:
通過使用模板方法模式,可以將一些複雜流程的實現步驟封裝在一系列基本方法中,在抽象父類中提供一個稱之為模板方法的方法來定義這些基本方法的執行次序,而通過其子類來覆蓋某些步驟,從而使得相同的演算法架構可以有不同的執行結果。
3、模板類,模板方法:
3.1、模板類可以是抽象類別,也可以是具體類,根據需要來確定。
3.2、模板類中的模板方法,一定是具體方法,其他方法可以使抽象方法也可以是具體方法;
3.3、通過繼承與多態的控制,可以實現子類對父子的反向控制;
4、demo
package com.example.demo.TemplateMethod;import android.util.Log;/** * 模版方法抽象類別 * @author qubian * @data 2015年6月9日 * @email naibbian@163.com * */public abstract class TemplateLotteryAbs {/** * 擷取隨機數 */protected abstract String getRandomNum(int num);/** * 處理隨即數產生的資料 */protected abstract void doLotteryString(String lottery);/** * 計算注數 */protected abstract void doLotteryNum();/** * 是否標紅 * @return */public boolean shouldSetStringRed(){return false;}/** * 標紅 */protected void SetStringRed(){Log.i("TemplateAbs", "SetStringRed");}/** * 模板方法:定義在抽象類別中,並由子類不加以修改地完全繼承下來。 * 模板方法是一個具體方法,它給出了一個頂層邏輯架構, * 而邏輯的組成步驟在抽象類別中可以是具體方法,也可以是抽象方法。 * 由於模板方法是具體方法,因此模板方法模式中的抽象層只能是抽象類別,而不是介面。 * */public void doInfo(int num){// 內部控制doLotteryString(getRandomNum(num));doLotteryNum();// 這可以通過 繼承覆蓋,反向控制父類的方法if (shouldSetStringRed()) {SetStringRed();}}}
具體方法:
package com.example.demo.TemplateMethod;import android.util.Log;/** * 模板方法子類 * @author qubian * @data 2015年6月9日 * @email naibbian@163.com * */public class TemplateLottery extends TemplateLotteryAbs{private static final String TAG ="TemplateObj";@Overrideprotected String getRandomNum(int num) {return "1,2,3,4,5,6";}@Overrideprotected void doLotteryString(String lottery) {Log.i(TAG, "doLotteryString");}@Overrideprotected void doLotteryNum() {}/** * 反向控制 */@Overridepublic boolean shouldSetStringRed() {return super.shouldSetStringRed();}@Overrideprotected void SetStringRed() {super.SetStringRed();}}
使用:
package com.example.demo.TemplateMethod;/** * 使用 模板方法模式 * @author qubian * @data 2015年6月9日 * @email naibbian@163.com * */public class UseTemplate {public void use(){TemplateLotteryAbs tempObj= new TemplateLottery();tempObj.doInfo(5);}}
7、在Android中的運用:
在Android源碼中,View中的Draw()方法就是一個“模板方法”。
當繼承View子類中,如果要重寫或者擴充這個方法時,整個方法流程和基本內容不能夠修改,
View 視圖的構建,都是由View自身實現,其中的演算法實現流程都是確定的;
子類只能通過擴充onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)兩個函數,使子類自己的View顯示效果和別的具體子類的不同。
其中有:TextView類中重寫了OnDraw函數,ViewGroup類,SurfaceView重寫了dispatchDraw()函數等等。
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { /** * 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) { }}
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { @Override protected void onDraw(Canvas canvas) { restartMarqueeIfNeeded(); // Draw the background for this view super.onDraw(canvas); final Drawables dr = mDrawables; if (dr != null) { //..... } int color = mCurTextColor; mTextPaint.setColor(color); mTextPaint.drawableState = getDrawableState(); canvas.save(); }