Template Patterns and BaseActivity

Posted by bruceleejr on Wed, 24 Jul 2019 03:55:13 +0200

I. Template pattern
In daily object-oriented development, there is sometimes a requirement that we know the key steps in the implementation of an algorithm or business logic, and determine the execution sequence of these steps; however, the specific implementation of individual/certain steps is unknown (with different environments or conditions changing). At this point, we can use the template pattern to deal with this situation, which not only meets the requirements, but also improves the reusability of the code and the flexibility of the code structure.

  1. Definition: When defining an algorithm framework for an operation, some steps are delayed to subclasses so that subclasses can redefine certain steps of the algorithm without changing the structure of an algorithm.

    AbstractClass: An Abstract class, which defines an algorithm framework.
    ConcreteClass: Specific implementation class, you can customize a set of algorithm framework;

This abstract class contains three types of methods: Abstract method, concrete method and hook method. The abstract method is implemented by subclasses. The concrete method is that the parent class implements the common method of subclasses. The hook method hook() is a default empty implementation method.

  1. Use scenarios, advantages and disadvantages of template method patterns
    (1) Use scenarios:
    When multiple subclasses have common methods and the logic is basically the same.
    Faced with important and complex algorithms, core algorithms can be designed as template methods, while peripheral details can be implemented by various subclasses.
    It is necessary to determine whether a step in the parent class algorithm is executed or not by subclasses, so as to achieve the reverse control of the parent class by subclasses.
    (2) Advantages:
    Template method patterns remove duplicate code from subclasses by moving invariant behavior to superclasses.
    The subclass implements some details of the algorithm, which is helpful to the expansion of the algorithm.
    (3) Disadvantages:
    Each different implementation needs to define a subclass, which leads to an increase in the number of classes and a more abstract design.

  2. A simple example
    Rough scenario: After a busy day, go home from work, do something when you get home, and then go to bed and rest after you finish your work. From the above scenario, we can get the following information:
    (1) Come home from work: you can take the subway, walk, drive, etc.
    (2) What to do after returning home: Usually most of the time, they are at their own discretion, but there may also be special circumstances that require overtime work at home;
    (3) After completing (2) things, wash and sleep;
    The code for the abstract class is as follows:

package com.example.tcl.myapplication.baselib;

public abstract class AfterWork{

    //Defined as final, no external modification of the algorithm's structure is allowed
    public final void execute(){
        goHome();
        doSomething();
        goSleeping();
    }

    //Hook method, empty implementation
    protected void hook(){}

    protected abstract void goHome();

    protected abstract void goSleeping();

    protected abstract void work();

    protected void doSomething(){
        if(isNeedWorking()){
            work();
        }
    }

    //Hook method, whether overtime is needed, default does not work overtime
    protected boolean isNeedWorking(){
        return false;
    }
} 

Take Biao Zhiwei as an example to inherit AfterWork class. The code is as follows:

package com.example.tcl.myapplication.baselib;
import android.util.Log;

public class BzwAfterWork extends AfterWork {
    private String TAG = "BzwAfterWork";
    @Override
    protected void goHome() {
        Log.i(TAG, "Riding home on my Baodonkey electric bike");
    }

    @Override
    protected void doSomething() {
        super.doSomething();
        Log.i(TAG, "Open the refrigerator and take out a bottle of Happy Water for the Otaku Man; Turn on the computer and see b station...");
    }

    @Override
    protected void goSleeping() {
        Log.i(TAG, "11 Yes, take a bath and go to bed.");
    }

    @Override
    protected void work() {
        //By default, no overtime is required. If overtime is required, the parent isNeedWorking() method is rewritten and true is returned.
    }
}
Use: 
BzwAfterWork bzwAfterWork = new BzwAfterWork();
bzwAfterWork.execute();
Operation results:
07-23 10:47:31.286 4097-4097/? I/BzwAfterWork:
    Riding home on my Baodonkey electric bike
    Open the refrigerator and take out a bottle of Happy Water for the homeboy. Turn on the computer and watch Station b.
    It's 11 o'clock. Take a bath and go to bed.

Encapsulation of BaseActivity
As the base class of Acitvity, it is mainly used to realize some common attributes and methods of Activity, optimize the code structure to a certain extent, reduce coupling, improve code readability, and facilitate modification and expansion; write specific functions into specific methods to achieve, while the logical requirements of a method are uncertain or uncertain. When the concrete operation is not clear, the abstract method is written and implemented by its subclasses.

package com.example.tcl.myapplication.baselib;

import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.WindowManager;


public abstract class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initStatus();
        setContentView();
        initView();
        initData();
    }

    //When the specific operation of the method is not clear, the abstract method is used.
    protected abstract void setContentView();
    protected abstract void initView();
    protected abstract void initData();

    //Start Activity
    protected void startActivity(Class<?> clazz){
        Intent intent = new Intent(this, clazz);
        startActivity(intent);
    }

    //findViewById
    public <T extends View>T getViewById(int viewId){
        return (T)findViewById(viewId);
    }
    
    protected void initStatus(){
        // Hide the title bar
        if (getSupportActionBar() != null)
            getSupportActionBar().hide();
        // Immersion effect
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Transparent status bar
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // Transparent navigation bar
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        }
    }

}

III. Use
The encapsulation method in BaseActivity is basically the method that every Activity will use; if only two or more methods will be used (not commonly used), it will usually be encapsulated as a tool class. When encapsulating, we must choose the appropriate way according to the specific usage.

public class TestActivity extends BaseActivity {
    @Override
    protected void setContentView() {
        setContentView(R.layout.activity_main);
        jumpToMainActivity();
    }

    /**
     * Initialization control
     */
    @Override
    protected void initView() {

    }

    /**
     * Initialization data
     */
    @Override
    protected void initData() {

    }
    
    private void jumpToMainActivity(){
        startActivity(MainActivity.class);
    }
}

Topics: Android REST