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.
API
YesAPI
Interface code friends all know, writeAPI
There 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 servicejson
You 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 methodAPI
Interface 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 aAPI
Interface
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 hereidea
OfTools
BelowREST Client
Carry out interface test:
enter image description here
enter image description here
Look at the consoleConsole
Printed information:
enter image description here
enter image description here
In this way, we can apply the template design pattern to our specific code, and we can also implement other modulesAPI
Implementation class of.
In addition, parameter verification can also be done in theAbstractTemplate
Implementation of adefault
For 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
AbstractApplicationContext
Inrefreash
Method 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
BaseExecutor
Inupdate
Method 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);
}
stayBaseExecutor
Only 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
BaseExecutor
The implementation classes are as follows:
enter image description here
Implementation classSimpleExecutor
IndoUpdate
Implementation 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 classReuseExecutor
IndoUpdate
Implementation 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.Mybatis
In 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?”