###1. Mode introduction


Definition of schema

A framework that defines an algorithm in an operation, deferring some steps to subclasses. Allows subclasses to redefine specific steps of an algorithm without changing its structure.

All shared outline: 2017Android road to progress with you

Video on address: http://pan.baidu.com/s/1nuNA0Vv

Usage scenarios of patterns

  1. Multiple subclasses have common methods and basically the same logic.
  2. For important and complex algorithms, the core algorithm can be designed as a template method, and the surrounding details are implemented by each subclass.
  3. In refactoring, the template method pattern is a frequently used pattern that extracts the same code into a parent class and then constrains its behavior with hook functions.

# # # 2. UML class diagram


Character is introduced

  • AbstractClass: AbstractClass that defines a set of algorithmic frameworks.
  • ConcreteClass1: Concrete implementation class 1;
  • ConcreteClass2: Concrete implementation class 2;

###3. Simple implementation of the pattern


The simple implementation of the introduction template approach encapsulates an algorithm framework, like a set of templates. Subclasses can have different algorithm implementations, and implement algorithm replacements without the framework being modified. Let’s briefly demonstrate the template method by turning on the computer. The whole process of opening the computer is relatively stable. First, turn on the power of the computer, and the computer will enter the operating system when it detects its own state and there is no problem. After verifying the user, you can log in the computer.

Realize the source

package com.dp.example.templatemethod; Public abstract class AbstractComputer {public abstract class AbstractComputer {public abstract class AbstractComputer {public abstract class AbstractComputerpowerOn() {
        System.out.println("Turn on the power");
    }

    protected void checkHardware() {
        System.out.println("Hardware Check");
    }

    protected void loadOS() {
        System.out.println("Load the operating system");
    }

    protected void login() {
        System.out.println("White's computer has no authentication. It's directly in the system."); } /** * The method of starting the computer, the steps are fixed as power on, system check, loading the operating system, user login. This method is final to prevent algorithm frames from being overwrittenstartUp() {
        System.out.println("------ START ------");
        powerOn();
        checkHardware();
        loadOS();
        login();
        System.out.println("------ boot END ------"); } } package com.dp.example.templatemethod; Public CoderComputer extends AbstractComputer {@override protected void public CoderComputer extends AbstractComputer {@override protected voidlogin() {
        System.out.println("All the code farmers need is user and password authentication."); } } package com.dp.example.templatemethod; /** * @author mrsimple */ public class MilitaryComputer extends AbstractComputer {@override protected voidcheckHardware() {
        super.checkHardware();
        System.out.println("Checking the Hardware Firewall");
    }

    @Override
    protected void login() {
        System.out.println("Perform complex user authentication such as fingerprint identification."); } } package com.dp.example.templatemethod; public class Test { public static void main(String[] args) { AbstractComputer comp = new CoderComputer(); comp.startUp(); comp = new MilitaryComputer(); comp.startUp(); }}Copy the code

The following output is displayed:

-- -- -- -- -- -- boot START -- -- -- -- -- -- check load the operating system on hardware Code farmers only requires user and password authentication is ok -- -- -- -- -- - on the END -- -- -- -- -- -- -- -- -- -- -- -- boot START -- -- -- -- -- - open source hardware check hardware firewall Load the operating system for fingerprint identification and other complex user authentication ------ boot END ------Copy the code

The startUp method has four fixed steps: power on, check hardware, load the system, and log in. These four steps do not change during the startUp process. But different users may implement these steps differently, so they can use different implementations. StartUp is the final method, which ensures that the algorithm framework cannot be modified, but the specific algorithm implementation can be flexibly changed. The startUp algorithm is a template method. Thus, the template method is a framework for defining an algorithm in an operation, deferring some steps to subclasses. Allows subclasses to redefine specific steps of an algorithm without changing its structure. As shown in figure:

###4. Pattern implementation in Android source code


In Android, a typical class that uses template methods and is well known to us is AsyncTask. For a more detailed analysis of AsyncTask, please refer to the use and source code analysis of AsyncTask in Android. We will only analyze the template method mode used in this class.

When using AsyncTask, we all have methods that take time to put in doInBackground(Params… Params, if you want to do something like initialization before doInBackground, you can do it in the onPreExecute method, and when doInBackground is done, it will execute onPostExecute, All we need to do is build AsyncTask and execute. As we can see, the entire implementation process is actually a framework, and the specific implementation needs to be subclassed. And its implementation algorithm framework is fixed, will in turn perform onPreExecute, after invoking the execute doInBackground, onPostExecute, of course you also can update progress by onProgressUpdate. We can simply understand it as the following pattern:

Let’s look at the source code, first let’s look at the entry to execute the asynchronous task, namely the execute method:

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;
    }
Copy the code

You can see that the execute method (a method of final type) calls the executeOnExecutor method, which determines the state of the task and throws an exception if it is not PENDING. This explains why AsyncTask can only be executed once. Therefore, if the task has already been executed, its state will become FINISHED. Moving on, we see that the onPreExecute method is executed first in the executeOnExecutor method, and that the method is executed on the UI thread. The params parameter is then passed to the mParams field of the mWorker object, and the exec.execute(mFuture) method is executed. What about mWorker and mFuture? MWorker simply implements the Callable interface and adds a parameter array field. Let’s take a look at each field one by one. Tracing the code, we can see that both fields are initialized in the constructor.

public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);

                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                return postResult(doInBackground(mParams)); }}; mFuture = new FutureTask<Result>(mWorker) { @Override protected voiddone() {
                try {
                    final Result result = get();

                    postResultIfNotInvoked(result);
                } catch (InterruptedException e) {
                    android.util.Log.w(LOG_TAG, e);
                } catch (ExecutionException e) {
                    throw new RuntimeException("An error occured while executing doInBackground()",
                            e.getCause());
                } catch (CancellationException e) {
                    postResultIfNotInvoked(null);
                } catch (Throwable t) {
                    throw new RuntimeException("An error occured while executing "
                            + "doInBackground()", t); }}}; }Copy the code

Simply put, mFuture wraps the mWorker object, calls the mWorker object’s call method, and returns it to the caller. For a more detailed analysis of AsyncTask, please refer to the Android AsyncTask usage and source code analysis. We only analyze the template method pattern here. In short, the Call method is called in the child thread, and the doInBackground method is called in the call method, so the doInBackground is executed in the child thread. The doInBackground returns the result, which is eventually posted to the UI thread via postResult. Let’s look at the postResult implementation:

private Result postResult(Result result) {
        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

    private static class InternalHandler extends Handler {
        @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;
            }
        }
    }


    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
Copy the code

What == MESSAGE_POST_RESULT (MSG. What == MESSAGE_POST_RESULT) sends a message to sHandler, whose type is InternalHandler. Result.mtask.finish (result.mdata [0]) is called when InternalHandler receives a message of type MESSAGE_POST_RESULT. Result AsyncTaskResult (AsyncTaskResult);

    @SuppressWarnings({"RawUseOfParameterizedType"}) private static class AsyncTaskResult<Data> { final AsyncTask mTask; final Data[] mData; AsyncTaskResult(AsyncTask task, Data... data) { mTask = task; mData = data; }}Copy the code

MTask is AsyncTask and onPostExecute is called when AsyncTask finishes. In short, execute method encapsulates the algorithm framework of onPreExecute, doInBackground and onPostExecute. Users can override these methods according to their own requirements, which makes it convenient for users to complete time-consuming operations with asynchronous tasks. You can use onPostExecute to update the UI thread. Another good example of a template method is the Activity declaration cycle function. For example, an Activity executes from a stylized template such as onCreate, onStart, and onResume. This is an Activity template method.

Next, let’s see how you can use it in development… Wait, I’m going to report you –> What? You copy from others. How do? Have you been caught? This is not plagiarism, I just put out good things to share with you. I recommend it to you: There are many design patterns, https://github.com/simple-android-framework-exchange/android_design_patterns_analysis#schedule You’d better buy a book to have a look at such a good thing or support it, I hope to produce some better (although I read the electronic document). Speaking of which, thank you very much for your gratuites. although it is not much, I really appreciate it from the bottom of my heart. I hope there will be more good articles in the future. I have checked a lot of template design patterns on the Internet, which are simply introduced to the concept and then write a small story, such as: programmer’s day, bank business and so on. I shaved a baldheaded recently, because go to work idle come to have nothing to do when reading other people’s blog always scratch hair, all the time think I should use where? Where can it be used? . So he shaved his head.

Because it is still in the system architecture part of the content section of the sub-project, and every project must be inseparable from the Activity, in the Activity of the onCreate() method is basically: set the layout -> initialize the head -> initialize the interface -> initialize the data. If we follow such a process is it just in line with our template design mode?

/** * Created by Darren on 2017/2/8. * Email: [email protected] * Description: The BaseActivity */ public abstract class BaseActivity extends AppCompatActivity {@override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(); initTitle(); initView(); initData(); } // initialize data. // Initialize interface protected abstract void initView(); // Set interface view protected abstract voidsetContentView(); // Initialize header protected abstract void initTitle(); }Copy the code

In the future, every time we build a new Activity, we will not inherit directly from AppCompatActivity, but our own BaseActivity will automatically ask us to copy several abstract methods in BaseActivity, and we will write corresponding code in the method.

/** * Created by Darren on 2017/2/8. * Email: [email protected] * Description: MainActivity */ public class MainActivity extends BaseActivity {@override protected voidinitData() {

    }

    @Override
    protected void initView() {

    }

    @Override
    protected void setContentView() {
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void initTitle() {}}Copy the code

I will talk about it later. We will extend BaseActivity first. Some common processes and functions can be put in BaseActivity, such as creating a set of IOC annotation framework and launching activities.

/** * Created by Darren on 2017/2/8. * Email: [email protected] * Description: The BaseActivity */ public abstract class BaseActivity extends AppCompatActivity {@override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(); // IOC annotation inject viewutils.inject (this); initTitle(); initView(); initData(); } // initialize data. // Initialize interface protected abstract void initView(); // Set interface view protected abstract voidsetContentView(); // Initialize header protected abstract void initTitle(); /** * start an Activity * @param Activity Class */ public void startActivity(Class<? extends Activity> activity) { Intent intent = new Intent(this,activity); startActivity(intent); } public <T extends View> T viewById(@idres int resId) {return(T) super.findViewById(resId); }}Copy the code

Now let’s talk about the benefits, the benefits of the template design pattern, not just the benefits of doing it online too much, but the benefits of doing it in real development

  1. In the actual development process we are often not a person in the development, if the direct in onCreate() to write a lot of things obviously not, but if you write some methods, so each member of the method will be different, let alone some of the brothers English estimate did not pass four, the word is wrong;
  2. Direct inheritance from BaseActivity will automatically suggest the overwrite method, more conducive to development or code reading, each method to do their own job only do what they should do, nothing to do on the rest;
  3. We can put some generic processes or some methods into BaseActivity, which saves code and makes it easier but it’s not a mess, and there’s a lot of details that you can see in the video;
  4. We definitely need BaseActivity at the logical level, which actually facilitates later version iteration, hierarchy extraction, and code refactoring…

All shared outline: 2017Android road to progress with you

Video on address: http://pan.baidu.com/s/1nuNA0Vv