3. Behavioral mode [template mode, callback]

Template mode

Mainly used to solve the two problems of reuse and expansion

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

Template mode function 1: reuse

The template pattern abstracts the unchanged process of an algorithm into the template method of the parent class, leaving the variable parts to the subclass for implementation. All subclasses can reuse the process code defined by the template method in the parent class .

  • The Java InputStream
    read(byte b[], int off, int len) function is a template method that defines the entire process of reading data and exposes the read() abstract method customized by subclasses.
public abstract class InputStream implements Closeable {
    
    
    //...省略其他代码...
    public int read(byte[] b, int off, int len) throws IOException {
    
    
        if (b == null) {
    
    
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
    
    
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
    
    
            return 0;
        }
        int c = read();
        if (c == -1) {
    
    
            return -1;
        }
        b[off] = (byte) c;
        int i = 1;
        try {
    
    
            for (; i < len; i++) {
    
    
                c = read();
                if (c == -1) {
    
    
                    break;
                }
                b[off + i] = (byte) c;
            }
        } catch (IOException ee) {
    
    
        }
        return i;
    }

    public abstract int read() throws IOException;
}


public class ByteArrayInputStream extends InputStream {
    
    
    //...省略其他代码...
    @Override
    public synchronized int read() {
    
    
        return (pos < count) ? (buf[pos++] & 0xff) : -1;
    }
}
  • The Java AbstractList
    addAll() function can be regarded as a template method. add() is a method that subclasses need to override. Although it is not declared abstract, the function implementation directly throws an UnsupportedOperationException exception. The premise is that it cannot be used by subclasses without overriding it.
public abstract class AbstractList {
    
    
    public boolean addAll(int index, Collection<? extends E> c) {
    
    
        rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
    
    
            add(index++, e);
            modified = true;
        }
        return modified;
    }

    public void add(int index, E element) {
    
    
        throw new UnsupportedOperationException();
    }
}

Template mode function two: expansion

The expansion here does not refer to the extensibility of the code, but to the extensibility of the framework. The framework provides functional extension points through the template mode, allowing framework users to customize the functions of the framework based on the extension points without modifying the framework source code.

  • Java Servlet
    uses a relatively low-level Servlet to develop Web projects. You only need to define a class that inherits HttpServlet, and rewrite the doGet() or doPost() method in it to handle get and post requests respectively.


    The Servlet container will receive the corresponding request, find the corresponding Servlet based on the mapping relationship between the URL and the Servlet, and then execute its service() method. The service() method is defined in the parent class HttpServlet. It calls
    the doGet() or doPost() method and then outputs the data to the web page.


    The service() method of HttpServlet is a template method, which implements the execution process of the entire HTTP request. doGet() and doPost() are parts of the template that can be customized by subclasses.


    The Servlet framework provides an extension point (doGet(), doPost() methods), allowing framework users to embed business code into the framework for execution through the extension point without modifying the Servlet framework source code.

  • JUnit TestCase
    The JUnit framework also provides some functional extension points (setUp(), tearDown(), etc.) through the template mode, allowing framework users to extend functions on these extension points.


    When using the JUnit testing framework to write unit tests, the test classes written must inherit the TestCase class provided by the framework. In the TestCase class, the runBare() function is a template method, which defines the overall process of executing a test case: first execute setUp() to
    do some preparatory work, then execute runTest() to run the real test code, and finally execute tearDown() to do the test. Cleaning up work.

callback

Compared with ordinary function calls, callbacks are a two-way calling relationship. Class A registers a certain function F to class B in advance. When class A calls the P function of class B, class B in turn calls the F function registered to it 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".

  • Synchronous callback means executing the callback function before the function returns;
public interface ICallback {
    
    
    void methodToCallback();
}

public class BClass {
    
    
    public void process(ICallback callback) {
    
    
//...
        callback.methodToCallback();
//...
    }
}

public class AClass {
    
    
    public static void main(String[] args) {
    
    
        BClass b = new BClass();
        b.process(new ICallback() {
    
     //回调对象
            @Override
            public void methodToCallback() {
    
    
                System.out.println("Call back me.");
            }
        });
    }
}
  • Asynchronous callback refers to executing the callback function after the function returns

    The payment function is implemented through a three-party payment system. After the user initiates a payment request, the user generally does not block until the payment result is returned, but registers a callback interface (similar to a callback function, usually a callback URL) to the three-party payment system, etc. After the execution of the three-party payment system is completed, the results are returned to the user through the callback interface.

  • Spring JdbcTemplate
    JdbcTemplate further encapsulates JDBC to simplify database programming. To use JdbcTemplate to query user information, you only need to write code related to this business, including the SQL statement for querying users and the
    mapping relationship between query results and User objects. Other process codes (loading drivers, creating database connections, creating statements, closing connections, closing statements, handling exceptions) are all encapsulated in the JdbcTemplate class, and we do not need to rewrite them every time.

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;
        }
    }
}

//  JdbcTemplate 通过回调的机制,将不变的执行流程抽离出来,放到模板方法 execute() 中,将可变的部分设计成回调 StatementCallback,由用户来定制。query() 函数是对 execute() 函数的二次封装,让接口用起来更加方便。


Template pattern VS callback

  • Application scenarios

    Synchronous callbacks are almost identical to template patterns. They are all in a large algorithm skeleton, and certain steps can be freely replaced for the purpose of code reuse and expansion.


    Asynchronous callbacks are quite different from the template pattern, and are more like the observer pattern.

  • Code

    Callback is implemented based on the combination relationship. Passing one object to another object is a relationship between objects. The


    template pattern is implemented based on the inheritance relationship. The subclass overrides the abstract method of the parent class, which is a relationship between classes.

  • Composition is better than inheritance! In terms of code implementation, callbacks are more flexible than template mode.

    1. Java only supports single inheritance languages. A subclass written based on the template pattern has inherited a parent class and no longer has the ability to inherit.

    2. Callbacks can use anonymous classes to create callback objects without defining the class in advance; the template pattern must define different subclasses for different implementations.

    3. If multiple template methods are defined in a class, and each method has a corresponding abstract method, then even if we only use one of the template methods, the subclass must implement all abstract methods. The callback is more flexible. We only need to inject the callback object into the template method used.

Guess you like

Origin blog.csdn.net/weixin_46488959/article/details/126919274