Template mode of design mode

concept

The template method pattern defines an algorithm skeleton in a method and defers some steps to subclasses. The template method pattern allows subclasses to redefine some steps in the algorithm without changing the overall structure of the algorithm.

When there is a long process in the project, but the specific implementation is different in different scenarios, the algorithm skeleton can be defined, that is, the common logic in different scenarios can be abstracted into methods where different implementations are required, and implemented by subclasses.

Template design pattern solves the problem of reuse and extension.

Benefits: code reuse and reduce duplicate code. Except for the specific methods to be implemented by the subclass, other methods and method call sequences are written in advance in the parent class.

Mode of use

Key points:

  • Define the algorithm skeleton and abstract it as a parent class;
  • The subclass inherits the parent class, and the subclass implements the logic in different scenarios;

for instance

Take the test paper as an example. One test paper needs to be copied for students. The test questions are the same, and the short answers and names of each test paper are different. Then you can abstract out such a parent class.

abstract class Paper {
    abstract String getName();  //Get student name
    abstract String getResult();  //Get students' answers
    
    public void getPaperContent() {   //Get the content of the test paper
        System.out.println("I am"+ getName() + ",My answer is"+ getResult());
        //....
    }
}

Then the student's test paper can inherit this parent class, and the specific implementation will be handed over to the child class.

class StudentPaPer1 extends Paper {
    @Override
    public String getName() {
        return "Zhang San";
    }
    @Override
    public String getResult(){
         return "a";
    }
    
}

class StudentPaPer2 extends Paper {
    @Override
    public String getName() {
        return "Li Si";
    }
    @Override
    public String getResult(){
         return "b";
    }
    
}

Then the calling method becomes

public static void main(String[] args) {
    Paper student1 = new StudentPaPer1();
    Paper student2 = new StudentPaPer2();
    
    student1.getPaperContent();
    student2.getPaperContent();
    //...
}

PS: in fact, it encapsulates common logic by using the characteristics of inheritance;

extend

Using template design pattern can reduce repeated code, which is implemented by subclasses by defining abstract methods. Using * * Callback * * can also play the role of reuse and expansion.

The concept of callback

Compared with ordinary function calls, callback is a two-way calling relationship. Class a registers a function f to class B in advance. When class a calls the P function of class B, class B calls the F function registered by class A. The F function here is the "callback function". A calls B, and B in turn calls A. this calling mechanism is called "callback".

How does class A register callback functions with class B? In Java, class A callback objects can be passed into class B.

public interface ICallback {
	void methodToCallback();
}

/**
* Encapsulate public logic
**/
public class B {
	public void process(ICallback callback) {
		//...
		callback.methodToCallback();
		//...
	}
}

// Callback implementation class
public class A implements ICallback {
    @Override      
	public void methodToCallback() {     
        System.out.println("call back invoke...");     
    }
}

// Client call
public class Demo {
	public static void main(String[] args) {
		B b = new B();
        // Create objects using anonymity
		b.prpcess(new ICallback(){
			 @Override      
			 public void methodToCallback() {     
             	System.out.println("call back invoke...");     
             }
		});
        
        // You can also create an A object instance directly
        A a = new A();
        b.process(a);
	}
}

In the Demo client, a class B object is created. When calling the B#process method, the anonymous object is created as a callback object and passed to the process method, so that B can execute specific scenario methods in the execution process;

If there are new scenarios in the future, you only need to create an object that implements the ICallback callback class to realize code reuse and extension.

Scenario 1: JdbcTemplate

public class JdbcTemplateDemo {
  private JdbcTemplate jdbcTemplate;

  public User queryUser(long id) {
    String sql = "select * from user where id="+id;
    return jdbcTemplate.query(sql, new UserRowMapper()).get(0);
  }

  class UserRowMapper implements RowMapper<User> {
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
      User user = new User();
      user.setId(rs.getLong("id"));
      user.setName(rs.getString("name"));
      user.setTelephone(rs.getString("telephone"));
      return user;
    }
  }
}

The JdbcTemplate reuses cumbersome process steps such as loading drivers, creating database connections, creating statements, closing connections, closing statements, and handling exceptions; For different SQL, the process code can be reused; When using, you only need to create the implementation of RowMapper and pass the object as a callback object to the method, so as to realize code reuse and extension.

Scenario 2: JVM hook method

The JVM provides the runtime. Addshutdown hook (thread hook) method, which can register a hook closed by the JVM. Hook is a hook. When the application is closed, the JVM will automatically call the hook code.

public class ShutdownHookDemo {

  private static class ShutdownHook extends Thread {
    public void run() {
      System.out.println("I am called during shutting down.");
    }
  }

  public static void main(String[] args) {
    Runtime.getRuntime().addShutdownHook(new ShutdownHook());
  }
}

The logic about hooks is encapsulated in the ApplicationShutdownHooks class. When the application closes, the JVM will call the runHooks() method of this class to create multiple threads and execute multiple hooks concurrently. After registering the Hook, we don't need to wait for the Hook execution to complete, so this is also an asynchronous callback.

Differences and relations between template design and callback methods

In terms of code implementation, callbacks are implemented by using composite relationships, passing one object to another, which is a relationship between objects; The template is implemented by inheritance, and the subclass overrides the abstract method of the parent class, which is a relationship between classes;

It can be seen that the callback mode is more flexible than the template mode, which is mainly reflected in the following points:

  • Java is single inheritance. Subclasses written based on template pattern no longer have the characteristics of inheritance;
  • Callbacks can use anonymous classes to create callback objects without defining classes in advance; The template pattern defines different subclasses for different implementations;
  • If multiple template methods are defined in a class, and each method has a corresponding abstract method, even if we only use one of the template methods, the subclass must implement all the abstract methods. The callback is more flexible. We only need to inject the callback object into the template method used.

Keywords: Java Design Pattern

Added by mhoward on Fri, 17 Sep 2021 23:59:55 +0300