Learn template mode in five minutes

Time:2021-2-22

Learn template mode in five minutes

summary

Template pattern is to define an algorithm skeleton in an operation, and then delay some steps to subclasses. Template method enables subclasses to redefine some steps of the algorithm without changing the structure of the algorithm.

Usage scenarios

Drink tea

We all know that the basic steps (algorithm skeleton) of tea making are as follows:

Boil water, make tea, drink tea.

The key step in the whole process is to make tea. What kind of tea do you need to make? How long? Leave it to the subclass to implement.

Learn template mode in five minutes

API

YesAPIInterface code friends all know, writeAPIThere are generally four steps:

Parameter analysis, parameter verification, business processing and organization return parameters.

The request parameters are parsed into the request parameters of the servicejsonYou can use a common way to check the parameters, that is, to determine whether the parameters are empty, or you can define a special check method yourself. In general, each interface is different in business processing, and it is basically implemented by yourself. As for the return parameters, you may have to use this methodAPIInterface service.

Payment order

People who have done payment related systems know that payment orders are roughly divided into these three steps:

The organization requests the request parameters of the bank or the third-party payment company, initiates the payment, and processes the returned results.

The steps in the above three scenarios are the algorithm skeleton. As for each step, everyone may have different tea preferences, different API interface business, different payment processing of bank or third-party payment, and they may need to do their own special processing.

Scene reality

Implement aAPIInterface

Algorithm class

package com.tian.springbootdemo.controller;
import com.tian.springbootdemo.rep.Result;
/**
 *@ mother: Lao Tian
 *@ Description: template class
 */
public abstract class AbstractTemplate {
​
 /**
 *Algorithm skeleton
 */
 public Result execute() {
 //Step 1: analyze the parameters
 parseRequestParameters();
 //Step 2: check the parameters
 checkRequestParameters();
 //Step 3: business processing
 Object data= doBusiness();
 //Step 4: organize return parameters
 return assembleResponseParameters(data);
 }
​
 /**
 *Analytic parameters
 */
 public abstract void parseRequestParameters();
​
 /**
 *Calibration parameters
 */
 public abstract void checkRequestParameters();
​
 /**
 *Business processing
 */
 public abstract Object doBusiness();
​
 /**
 *Organization return parameters
 */
 public abstract Result assembleResponseParameters(Object object);
}

Implementation class I

import com.tian.springbootdemo.rep.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
​
/**
 *@ mother: Lao Tian
 *@ Description: API interface
 */
@RequestMapping("/api")
@Controller
public class MyApiController extends AbstractTemplate {
​
 @RequestMapping(value = "/users", method = RequestMethod.POST)
 @ResponseBody
 @Override
 public Result execute() {
 return super.execute();
 }
​
 @Override
 public void parseRequestParameters() {
 System.out.println ("* * * * * * * *");
 }
​
 @Override
 public void checkRequestParameters() {
 System.out.println ("* * * * * * * *");
 }
​
 @Override
 public Object doBusiness() {
 System.out.println ("* * * * * * * *");
 //Todo: call service to process business on November 17, 2018
 User user = new User();
 user.setName (brother OTA);
 user.setId(1);
 user.setAge(20);
 user.setSex("man");
 return user;
 }
​
 @Override
 public Result assembleResponseParameters(Object object) {
 System.out.println ("* * * * * * * *");
 Result result = new result ("200", "processing succeeded");
 result.setData(object);
 return result;
 }
}

Implementation class 2

import com.tian.springbootdemo.dao.domain.User;
import com.tian.springbootdemo.rep.Result;
import org.springframework.web.bind.annotation.*;
​
/**
 *@ mother: Lao Tian
 *@ Description: API interface
 */
@RequestMapping("/api")
@RestController
public class LoginController extends AbstractTemplate {
 @PostMapping(value = "/login")
 @Override
 public Result execute() {
 return super.execute();
 }
 @Override
 public void parseRequestParameters() {
 System.out.println ("resolve login parameters");
 }
​
 @Override
 public void checkRequestParameters() {
 System.out.println ("verify whether the login user name is empty and the password is empty");
 }
​
 @Override
 public Object doBusiness() {
 System.out.println ("query whether this user exists through user name");
 System.out.println ("check whether the user password is correct");
 System.out.println ("login successful");
 User user = new User();
 user.setName (brother OTA);
 user.setId(1);
 user.setAge(20);
 user.setSex("man");
 return user;
 }
​
 @Override
 public Result assembleResponseParameters(Object object) {
 System.out.println ("* * * * * * * *");
 Result result = new result ("200", "login successful");
 result.setData(object);
 return result;
 }
}

Related classes

/**
 *@ mother: Lao Tian
 *@ Description: return information
 */
public class Result {
 //Return code
 private String responseCode;
 //Description
 private String message;
 //Data
 private Object data;
​
 public Result() {
 }
​
 public Result(String responseCode, String message) {
 this.responseCode = responseCode;
 this.message = message;
 }
​
 public Result(String responseCode, String message, Object data) {
 this.responseCode = responseCode;
 this.message = message;
 this.data = data;
 }
​
 public String getResponseCode() {
 return responseCode;
 }
​
 public void setResponseCode(String responseCode) {
 this.responseCode = responseCode;
 }
​
 public String getMessage() {
 return message;
 }
​
 public void setMessage(String message) {
 this.message = message;
 }
​
 public Object getData() {
 return data;
 }
​
 public void setData(Object data) {
 this.data = data;
 }
}
​
import java.io.Serializable;
​
/**
 *@ mother: Lao Tian
 *@ Description: Data
 */
public class User implements Serializable {
 //id
 private Integer id;
 //User name
 private String name;
 //Gender
 private String sex;
 //Age
 private int age;
​
 public User() {
 }
​
 public User(Integer id, String name, String sex, int age) {
 this.id = id;
 this.name = name;
 this.sex = sex;
 this.age = age;
 }
​
 public Integer getId() {
 return id;
 }
​
 public void setId(Integer id) {
 this.id = id;
 }
​
 public String getName() {
 return name;
 }
​
 public void setName(String name) {
 this.name = name;
 }
​
 public String getSex() {
 return sex;
 }
​
 public void setSex(String sex) {
 this.sex = sex;
 }
​
 public int getAge() {
 return age;
 }
​
 public void setAge(int age) {
 this.age = age;
 }
}

test

It’s used hereideaOfToolsBelowREST ClientCarry out interface test:

Learn template mode in five minutes

enter image description here

Learn template mode in five minutes

enter image description here

Look at the consoleConsolePrinted information:

Learn template mode in five minutes

enter image description here

Learn template mode in five minutes

enter image description here

In this way, we can apply the template design pattern to our specific code, and we can also implement other modulesAPIImplementation class of.

In addition, parameter verification can also be done in theAbstractTemplateImplementation of adefaultFor example: check whether the parameter is empty, but the subclass can also override this method to do a special check; for example: if there is a mobile phone number in the parameter, we not only need to check whether the mobile phone number is empty, but also can check whether the mobile phone number is 11 digits, whether it is legal, and so on.

Advantages and disadvantages of template mode

advantage

  • Improve the reusability of the code, put the same part of the code into the abstract class;
  • Improve the expansibility, put different into different implementation classes, and add some needed behaviors through the extension of implementation classes;
  • Reverse control is realized by calling a parent class to implement the operation of the class, and by adding new behaviors to the extension of the implementation class, reverse control is realized.

shortcoming

  • Because of the introduction of abstract classes, each different implementation needs a subclass to realize, which will lead to the increase of the number of classes and the complexity of system implementation.

How do the big guys use it in the frame?

In spring

AbstractApplicationContextInrefreashMethod is the template method, the source code is:

@Override
public void refresh() throws BeansException, IllegalStateException {
 synchronized (this.startupShutdownMonitor) { 
 //Call the method that the container is ready to refresh to obtain the current time of the container,
 //At the same time, the synchronization identifier is set for the container
 prepareRefresh();
 //Tell the subclass to start the refreshbeanfactory() method,
 //Bean defines the loading of resource files
 //The refreshbeanfactory() method of the subclass starts
 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 //Configure container features for beanfactory, such as class loader, event handler, etc
 prepareBeanFactory(beanFactory);
 try { 
 //Specify a special beanpost event handler for some subclasses of the container
 //-----Subclass implementation
 postProcessBeanFactory(beanFactory);
 //Call the bean of all registered beanfactorypostprocessor
 invokeBeanFactoryPostProcessors(beanFactory);
 //Register the beanpost event handler for beanfactory
 //Beanpostprocessor is a bean postprocessor,
 //Used to listen for container triggered events
 registerBeanPostProcessors(beanFactory);
 //Initialization information source, and internationalization related
 initMessageSource();
 //Initializes the container event propagator
 initApplicationEventMulticaster();
 //Calling some special bean initialization methods of subclasses
 //-----Subclass implementation
 onRefresh();
 //Register the event listener for the event propagator
 registerListeners();
 //Initialize all remaining singleton beans
 finishBeanFactoryInitialization(beanFactory);
 //Initializes the lifecycle event handler of the container,
 //And publish the life cycle events of the container
 finishRefresh();
 //.....

This method is the context start template method. This is one of the application scenarios of template pattern in spring.

In mybatis

Learn template mode in five minutes

BaseExecutorInupdateMethod is a template method

/**
 *  SqlSession.update/insert/delete This method is called
 *Template method
 */
 @Override
 public int update(MappedStatement ms, Object parameter) throws SQLException {
 ErrorContext.instance().resource(ms.getResource()).activity("executing an                update").object(ms.getId());
 if (closed) {
 throw new ExecutorException("Executor was closed.");
 }
 //First clear the local cache, and then update. How to update the subclass,
 //Template method mode
 clearLocalCache();
 //Implemented by subclass (hook method)
 return doUpdate(ms, parameter);
 }

stayBaseExecutorOnly methods are defined in, but implementation is in subclasses

//Update 
protected abstract int doUpdate(MappedStatement ms, Object parameter)
 throws SQLException;
//Inquiry
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds 
 rowBounds, ResultHandler resultHandler, BoundSql boundSql)
 throws SQLException;
 //The methods starting with... Do are all implemented by the specific subclass itself

BaseExecutorThe implementation classes are as follows:

Learn template mode in five minutes

enter image description here

Implementation classSimpleExecutorIndoUpdateImplementation of the method

@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
 Statement stmt = null;
 try {
 Configuration configuration = ms.getConfiguration();
 //Create a new statementhandler
 //Here you can see that null is passed in by resulthandler
 StatementHandler handler = configuration.newStatementHandler(
 this, ms, parameter,          RowBounds.DEFAULT, null, null);
 //Prepare statement
 stmt = prepareStatement(handler, ms.getStatementLog());
 //StatementHandler.update
 return handler.update(stmt);
 } finally {
 closeStatement(stmt);
 }
}

Implementation classReuseExecutorIndoUpdateImplementation of the method

@Override
 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
 Configuration configuration = ms.getConfiguration();
 //Like simpleexecution,
 //Create a new statementhandler
 //Here you can see that null is passed in by resulthandler
 StatementHandler handler = configuration.newStatementHandler(
 this, ms, parameter,       RowBounds.DEFAULT, null, null);
 //Prepare statement
 Statement stmt = prepareStatement(handler, ms.getStatementLog());
 return handler.update(stmt);
 }

This is it.MybatisIn the template method pattern of the classic application.

summary

Template method pattern defines an algorithm skeleton, and then each implementation class implements its own business logic. There are good implementation cases in spring, mybatis, Dubbo and other frameworks. Relatively speaking, the template method mode is relatively simple. I can talk with the interviewer for a while in the interview.

“For the sake of a better future, what is it to be bitter now?”