intentions

Define the skeleton of an algorithm in an operation, defer some steps to subclasses, and Template Method allows subclasses to redefine specific steps of an algorithm without changing the structure of the algorithm

Birth of the template method pattern

The template method pattern provides an important technique for code reuse by defining algorithmic steps and deferring the implementation of those steps to subclasses

In human language:

[Product] : Development brother, can you cook?

[Development] : No, why? Are you gonna make it for me?

[Product] : You think too much, I am ready to teach you to do a fried cabbage ~, with you write code ideas, I also try to write pseudo code

public void cookie(a){
    // Step 1: Pour the oil
    this.pourOil();
    // Step 2: Heat the oil
    this.HeatOil();
 // Step 3: Pour the cabbage  this.pourVegetable();  // Step 4: Add the seasonings  this.pourSauce();  // Step 5: Stir fry  this.fry(); } Copy the code

[Development] : I understand, little sister, you want to come to my home? I’ll make you a stir-fried garlic paste

[Product] :?? Didn’t you say you couldn’t cook?

[Dev] : You wrote out the steps, I already know, hehe hehe ~

If you have not yet, then let’s look at the core code together ~ if you will, then directly jump to SSO combat ~

HeadFirst core code

An abstract class

public abstract class TemplateClass {

 / * * ** Template method, used to control the process of cooking (the process of cooking is the same - reuse)* Can be declared final according to the requirement, preventing subclasses from overwriting this method, resulting in the process execution order* /  final void cookProcess(a) {   // Step 1: Pour the oil  this.pourOil();   // Step 2: Heat the oil  this.heatOil();   // Step 3: Pour the vegetables  this.pourVegetable();   // Use the hook function to determine if you need to add seasoning  if (needSauce()) {  this.pourSauce();  }   // Step 5: Stir fry  this.fry();  }   void pourOil(a) {  System.out.println("Oil");  }   void heatOil(a) {  System.out.println("Hot oil");  }   / * * ** The parts that need to be changed are defined as abstractions* /  abstract void pourVegetable(a);  abstract void pourSauce(a);   / * * ** Hook functions that affect method call logic* /  boolean needSauce(a) {  return true;  }   void fry(a) {  System.out.println("Saute and saute and saute until it's cooked.");  } } Copy the code

The subclass implementation

public class SuanRong extends TemplateClass {

 @Override
 boolean needSauce(a) {
  return false;
 }   @Override  void pourVegetable(a) {  System.out.println("The vegetable in the pot is choi Xin.");  }   @Override  void pourSauce(a) {  System.out.println("The sauce is minced garlic.");  } } Copy the code

Design idea of template method pattern:

  • AbstractClass abstracts base classes, defines abstract methods, method invocation order, and so on
  • ConcreteClass inherits from an abstract base class to implement predefined methods

In short,

  1. We need an abstract class or interface (interfaces can also provide concrete methods after Java8) that defines the methods that need to be implemented and the method execution logic
  2. Inheriting abstract classes or interfaces based on business situations, implementing specific methods, makes multiple situations isolated from each other
  3. Implement classes that are reasonably built, such as by policy or other means

If this seems a bit ambiguous, I recommend that after reading this article, you visit the Thematic Design Patterns Open source project, which has specific code examples linked at the bottom

The power of templates: 5 minutes per SSO

When it comes to using the template method pattern for SSO, we need to know what SSO is.

SSO

SSO is single sign-on (SSO). In multiple systems, a user only needs to log in once, and each system will know that the user has logged in.

Common user authentication methods

This article mainly focuses on the actual combat of design mode, so simply say a few words, common ways such as:

  • The 2.0
  • cookie
  • .

The first SSO

When we wrote the first SSO, it was a bit of a struggle, thinking about processes, details, and so on

(This refers to our integration with other companies’ authentication systems)

The company I work for has various technical levels and technical stacks, so it is not the standard OAUTH2.0 structure. The following core links are abstractly abstrused, such as:

public interface SSOContextAnalysis {

    /** Jump login */
    void toLogin(SSOConfig ssoConfig, HttpServletResponse httpServletResponse);

 /** Obtain token */  Object getToken(SSOConfig ssoConfig, HttpServletRequest httpServletRequest);   / * * ** Get user information * @paramSsoConfig configuration * @returnEncrypted string of user information* /  String getUserInfo(SSOConfig ssoConfig, Object arg);   / * * ** Parse the SSO context* /  String getAccount(SSOConfig ssoConfig, Object userInfo);   /** 进行退出 */  boolean tologout(SSOConfig ssoConfig, UserOnline userOnline, HttpServletResponse httpServletResponse); } Copy the code

By SSO Demo

public class LongTuSSOHandle implements SSOContextAnalysis{

    @Override
    public void toLogin(SSOConfig ssoConfig) {
        // Skip to the SSO authentication address and set the callback address
 }   @Override  public Object getToken(SSOConfig ssoConfig) {  // Obtain Token information based on the encryption algorithm of the customer  return null;  }   @Override  public String getUserInfo(SSOConfig ssoConfig, Object arg) {  // Assemble packets, initiate user requests, and obtain user data  return null;  }   @Override  public String getAccount(SSOConfig ssoConfig, Object userInfo) {  // Obtain the user data of the platform based on the user data to complete the SSO process  return null;  }   @Override  public boolean tologout(SSOConfig ssoConfig) {  // Exit based on the exit address and so on  return false;  } } Copy the code

When we write business code, we rely entirely on the top-level abstract class, and then we can dynamically change the concrete implementation class

How do I dynamically specify implementation classes

The best ways to dynamically specify an implementation class are as follows:

  • Configuration file + Reflection build implementation class
  • Configuration file + Preloads all implementation classes, dynamically selected based on configuration
  • Database configuration + reflection (you can use the CGLIB agent)
  • Database configuration + Pre-loaded all implementation classes, dynamically selected based on configuration

How long will the second SSO take?

When we use the template method mode, the entire SSO process has been combed, the second SSO only need to implement the corresponding interface, and then according to the requirements of the customer to build different encryption protocols, at the same time to change the configuration, anyway, I only spent 5 minutes ~

Follow the design principles

  1. Packaging changes
    • In an abstract base class, we can have methods that are already implemented for subclasses to call
    • In an abstract base class, method logic that is necessarily different is defined as abstract for subclasses to implement themselves
  2. Hollywood principle
    • Don’t look for me, I will look for you to refer to the underlying code (the concrete implementation class) does not depend on the high-level code, we also reflected in this SSO practice, directly depend on the interface, the implementation class is only as the real implementer

What scenarios are suitable for use

  • Implement the invariant parts of an algorithm once and leave the mutable behavior to subclasses
  • Common behaviors in each subclass should be extracted and grouped into a common parent class to avoid code duplication
  • Control subclass extension (hook method mentioned in article, control method execution or not)

Code/ Practical application in life

We use all of the APP, for example, when to pay mostly can choose to pay, pay treasure or WeChat actually pay the whole step, only a specific payment steps is divided into a variety of situations (WeChat, alipay, bank CARDS, etc.), push the rest of the order data reverse is likely to be the same, we can use the template method pattern to constraint behavior, It also reduces duplication of code

PS: This situation may also be handled using policy mode, depending on the situation

The last

Attach the UML diagram for the template method pattern from the GOF book:

Related code links

Making the address

  • Examples from two classic books, HeadFirst and GOF
  • Provides friendly reading instructions