美文网首页
模板模式 - 行为型

模板模式 - 行为型

作者: 熊本极客 | 来源:发表于2020-05-04 11:19 被阅读0次

    一、模板模式的定义
    模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

    说明:这里的“算法”,我们可以理解为广义上的“业务逻辑”,并不特指数据结构和算法中的“算法”。这里的算法骨架就是“模板”,包含算法骨架的方法就是“模板方法”。

    解决的问题:复用和扩展。

    二、模板模式的实现
    已经实现templateMethod() 函数,是为了避免子类重写它。method1() 和 method2() 定义为 abstract,是为了强迫子类去实现。

    public abstract class AbstractClass {
      public void templateMethod() {
        //...
        method1();
        //...
        method2();
        //...
      }
      
      protected abstract void method1();
      protected abstract void method2();
    }
    
    public class ConcreteClass1 extends AbstractClass {
      @Override
      protected void method1() {
        //...
      }
      
      @Override
      protected void method2() {
        //...
      }
    }
    
    public class ConcreteClass2 extends AbstractClass {
      @Override
      protected void method1() {
        //...
      }
      
      @Override
      protected void method2() {
        //...
      }
    }
    
    AbstractClass demo = ConcreteClass1();
    demo.templateMethod();
    

    三、模板模式的应用场景
    1.复用
    Java IO 类库中,有很多类的设计用到了模板模式,比如 InputStream、OutputStream、Reader、Writer。InputStream如下所示。

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

    2.扩展
    基于扩展功能,模板模式常用在框架的开发中,让框架用户可以在不修改框架源码的情况下,定制化框架的功能。下面通过Java Servlet解释。

    public class HelloServlet extends HttpServlet {
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
      }
      
      @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Hello World.");
      }
    }
    

    下面的service() 方法定义在父类 HttpServlet 中,它会调用 doGet() 或 doPost() 方法,然后输出数据(“Hello world”)到网页。

    public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }
        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;
        service(request, response);
    }
    
    protected void service(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException
    {
        String method = req.getMethod();
        if (method.equals(METHOD_GET)) {
            long lastModified = getLastModified(req);
            if (lastModified == -1) {
                // servlet doesn't support if-modified-since, no reason
                // to go through further expensive logic
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
                if (ifModifiedSince < lastModified) {
                    // If the servlet mod time is later, call doGet()
                    // Round down to the nearest second for a proper compare
                    // A ifModifiedSince of -1 will always be less
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                }
            }
        } else if (method.equals(METHOD_HEAD)) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
        } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
        } else if (method.equals(METHOD_PUT)) {
            doPut(req, resp);
        } else if (method.equals(METHOD_DELETE)) {
            doDelete(req, resp);
        } else if (method.equals(METHOD_OPTIONS)) {
            doOptions(req,resp);
        } else if (method.equals(METHOD_TRACE)) {
            doTrace(req,resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
        }
    }
    

    相关文章

      网友评论

          本文标题:模板模式 - 行为型

          本文链接:https://www.haomeiwen.com/subject/jsueghtx.html