This is the second day of my participation in the November Gwen Challenge. Check out the details: the last Gwen Challenge 2021

Today, we’ll look at the second of behavioral design patterns: the template pattern.

The template pattern is mainly used to solve the problems of reuse and extension.

Without further ado, let’s begin today’s lesson.

introduce

Template Method Design Pattern: The Template Method Pattern defines an algorithm skeleton in a Method and postpones certain steps to subclasses. The template method pattern lets subclasses redefine certain steps in an algorithm without changing the overall structure of the algorithm.

Here the algorithm skeleton is the “template”, and the common code implementation is very simple.

Principle and Implementation

AbstracTemplate.java

public abstract class AbstracTemplate {

    public final void templateMethod(a) {
        methodA();
        methodB();
    }

    protected abstract void methodA(a);
    protected abstract void methodB(a);

}
Copy the code

ConcreteClassA. Java, ConcreteClassB. Java

public class ConcreteClassA extends AbstracTemplate {
    @Override
    protected void methodA(a) {
        System.out.println("Implement the ConcreteClassA method methodA");
    }

    @Override
    protected void methodB(a) {
        System.out.println("Implement the ConcreateClassA method methodB"); }}public class ConcreteClassB extends AbstracTemplate {

    @Override
    protected void methodA(a) {
        System.out.println("Implement the ConcreteClassB method methodA");
    }

    @Override
    protected void methodB(a) {
        System.out.println("Implement ConcreteClassB method methodB"); }}Copy the code

Test.java

public class Test {

    public static void main(String[] args) {

        AbstracTemplate classA = new ConcreteClassA();
        classA.templateMethod();
        System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =");
        AbstracTemplate classB = newConcreteClassB(); classB.templateMethod(); }}Copy the code

Results:

Function 1: reuse

One function of the template pattern: reuse

The template pattern abstracts the immutable flow of an algorithm into the parent templateMethod templateMethod(), leaving the mutable parts methodA() and methodB() to subclasses ConcreteClassA and ConcreteClassB. All subclasses can reuse the process code defined by the template methods in the parent class.

Java AbstractList

In a Java AbstractList class, the addAll() function can be thought of as a template method, and add() is a method that subclasses need to override, even though it is not declared abstract, But function directly throw UnsupportedOperationException anomalies. The premise is that you can’t use it if the subclass doesn’t override it.

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

Copy the code

As well as the Java IO library summary, there are a lot of class design also use the template pattern, such as InputStream, OutputStream, Reader, Writer.

Function 2: Expand

The second role of the template pattern: extension.

Based on this function, the template pattern is often used in framework development, allowing framework users to customize the functionality of the framework without modifying the framework source code. I remember when I was learning Java Web development, SERVlets were a must. When developing Web projects using servlets, we need to define a class that inherits HttpServlet and override the doGet() or doPost() methods to handle GET and POST requests, respectively. Specific code examples are as follows:

public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Hello World!"); }}Copy the code

When requested to the Servlet, its service() method is executed. The service() method, defined in the parent HttpServlet class, calls the doGet() or doPost() methods and outputs the data “Hello World” to the web page.

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    long lastModified;
    if (method.equals("GET")) {
        lastModified = this.getLastModified(req);
        if (lastModified == -1L) {
            this.doGet(req, resp);
        } else {
            long ifModifiedSince;
            try {
                ifModifiedSince = req.getDateHeader("If-Modified-Since");
            } catch (IllegalArgumentException var9) {
                ifModifiedSince = -1L;
            }

            if (ifModifiedSince < lastModified / 1000L * 1000L) {
                this.maybeSetLastModified(resp, lastModified);
                this.doGet(req, resp);
            } else {
                resp.setStatus(304); }}}else if (method.equals("HEAD")) {
        lastModified = this.getLastModified(req);
        this.maybeSetLastModified(resp, lastModified);
        this.doHead(req, resp);
    } else if (method.equals("POST")) {
        this.doPost(req, resp);
    } else if (method.equals("PUT")) {
        this.doPut(req, resp);
    } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
    } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
    } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
    } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[]{method};
        errMsg = MessageFormat.format(errMsg, errArgs);
        resp.sendError(501, errMsg); }}Copy the code

As you can see, the service() method is a template method that implements the entire HTTP request execution flow. DoGet () and doPost() are the parts of the template that can be customized by subclasses. In effect, the Servlet framework provides an extension point (doGet(), doPost()) that allows framework users to embed business code into the framework without modifying the Servlet framework source code.

conclusion

Advantages of the template pattern:

  • The detailed steps are defined in the subclass, and the detailed processing algorithm defined in the subclass will not change the overall structure of the algorithm.
  • The basic technology of code reuse is particularly important in database design.
  • There is a reverse control structure in which a parent class invokes operations of its subclasses and subclasses extend the parent class to add new behaviors, in accordance with the “open closed principle.”