Android 設計模式 - 模版方法模式
使用模版方法模式模擬不同計算機的啟動流程.
public abstract class AbstractComputer { protected void powerOn(){ System.out.println("開啟電源"); } protected void checkHardware(){ System.out.println("硬體檢查"); } protected void loadOS(){ System.out.println("載入作業系統"); } protected void login(){ System.out.println("小白的計算機無驗證,直接進入系統"); } /*** * */ public final void startUp(){ System.out.println("------ 開機 START ------"); powerOn(); checkHardware(); loadOS(); login(); System.out.println("------ 關機 START ------"); } }
public class CoderComputer extends AbstractComputer { @Override protected void login() { System.out.println("程式設計師只需要進行使用者和密碼的驗證就可以了"); } }
public class MilitaryComputer extends AbstractComputer{ @Override protected void checkHardware() { super.checkHardware(); System.out.println("檢查硬體和防火牆"); } @Override protected void login() { super.login(); System.out.println("進行指紋和複雜的使用者驗證"); } }
public static void main(String[] args){ AbstractComputer comp = new CoderComputer(); comp.startUp(); comp = new MilitaryComputer(); comp.startUp(); }
通過上面的例子可以看到,在startUp方法中有一些固定的步驟,依次為開啟電源,檢查硬體,載入系統,使用者登入4個步驟,這四個步驟是開機過程不會變動

image
但是,不同使用者的這幾個步驟的實現可能各不相同,因此,子類需要複寫相應的方法來進行自定義處理,這裡要注意startUp為final方法,這樣就保證了邏輯流程不能背子類修改,子類只能夠改變某一步驟中的具體實現,這樣保證了這個邏輯流程的穩定性。
Android中的模版方法模式
AsyncTask
@MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }
execute是一個final方法,這樣防止了子類充血,在executeOnExecutor中判斷了狀態,如果不是PENDING狀態就會丟擲異常,這也是為什麼AsyncTask中execute只能呼叫一次的原因,繼續往下看,會呼叫到onPreExecute(),那隨後的mWorker和mFuture是什麼?在建構函式中初始化了這兩個物件
public AsyncTask(@Nullable Looper callbackLooper) { mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { mTaskInvoked.set(true); Result result = null; try { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked result = doInBackground(mParams); Binder.flushPendingCommands(); } catch (Throwable tr) { mCancelled.set(true); throw tr; } finally { postResult(result); } return result; } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException("An error occurred while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }
mWorker其實是一個Callable,FutureTask對它進行了封裝,FutureTask的run函式又會呼叫call方法
public void run() { if (state != NEW || !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { //呼叫call方法 result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
在call方法中執行了AsyncTask的doInBackground方法,這裡是線上程池裡執行的.執行完過後呼叫到postResult(result)
private void postResultIfNotInvoked(Result result) { final boolean wasTaskInvoked = mTaskInvoked.get(); if (!wasTaskInvoked) { postResult(result); } }
postResult會發送一個訊息回撥到主執行緒
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
上面的getHandler()實際上是InternalHandler
private static class InternalHandler extends Handler { public InternalHandler(Looper looper) { super(looper); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } }
InternalHandler,接收到MESSAGE_POST_RESULT訊息過後會呼叫result.mTask.finish(result.mData[0]),result是AsyncTaskResult型別
private static class AsyncTaskResult<Data> { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; } }
AsyncTaskResult裡面的mTask就是AsyncTask,通過呼叫result.mTask.finish(result.mData[0])把結果通過finish返回到了AsyncTask的onPostExecute中.
這個過程整體上是用到模版方法模式

Activity的啟動流程
Activity的啟動流程實際上也是使用了模版方法,例如它的onCreate,onStart,onResume等生命週期方法. 具體的執行流程不再描述.
【附錄】

資料圖
需要資料的朋友可以加入Android架構交流QQ群聊:513088520
點選連結加入群聊【Android移動架構總群】: 加入群聊
獲取免費學習視訊,學習大綱另外還有像高階UI、效能優化、架構師課程、NDK、混合式開發(ReactNative+Weex)等Android高階開發資料免費分享。