Chinaunix首页 | 论坛 | 博客
  • 博客访问: 276791
  • 博文数量: 83
  • 博客积分: 2393
  • 博客等级: 大尉
  • 技术积分: 640
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-24 15:14
文章分类

全部博文(83)

文章存档

2019年(21)

2011年(5)

2010年(2)

2009年(1)

2008年(9)

2007年(33)

2006年(12)

我的朋友

分类: Java

2019-08-23 22:17:25



模板模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

介绍


意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
何时使用:有一些通用的方法。
如何解决:将这些通用算法抽象出来。
关键代码:在抽象类实现,其他步骤在子类实现。
应用实例: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。


https://www.cnblogs.com/wangkaihua/p/9123171.html

结构

AbstractClass:抽象类。用来定义算法骨架和原语操作,在这个类里面,还可以提供算法中通用的实现
ConcreteClass:具体实现类。用来实现算法骨架中的某些步骤,完成跟特定子类相关的功能。


点击(此处)折叠或打开

  1. /**
  2.  * 定义模板方法、原语操作等的抽象类
  3.  */
  4. public abstract class AbstractClass {
  5.     /**
  6.      * 原语操作1,所谓原语操作就是抽象的操作,必须要由子类提供实现
  7.      */
  8.     public abstract void doPrimitiveOperation1();
  9.     /**
  10.      * 原语操作2
  11.      */
  12.     public abstract void doPrimitiveOperation2();
  13.     /**
  14.      * 模板方法,定义算法骨架
  15.      */
  16.     public final void templateMethod() {
  17.         doPrimitiveOperation1();
  18.         doPrimitiveOperation2();
  19.     }
  20. }

  21. /**
  22.  * 具体实现类,实现原语操作
  23.  */
  24. public class ConcreteClass extends AbstractClass {
  25.     public void doPrimitiveOperation1() {
  26.         //具体的实现
  27.     }
  28.     public void doPrimitiveOperation2() {
  29.         //具体的实现
  30.     }
  31. }


模板方法模式在Servlet中的应用

  使用过Servlet的人都清楚,除了要在web.xml做相应的配置外,还需继承一个叫HttpServlet的抽象类。HttpService类提供了一个service()方法,这个方法调用七个do方法中的一个或几个,完成对客户端调用的响应。这些do方法需要由HttpServlet的具体子类提供,因此这是典型的模板方法模式。下面是service()方法的源代码:

点击(此处)折叠或打开

  1. protected void service(HttpServletRequest req, HttpServletResponse resp)
  2.         throws ServletException, IOException {

  3.         String method = req.getMethod();

  4.         if (method.equals(METHOD_GET)) {
  5.             long lastModified = getLastModified(req);
  6.             if (lastModified == -1) {
  7.                 // servlet doesn't support if-modified-since, no reason
  8.                 // to go through further expensive logic
  9.                 doGet(req, resp);
  10.             } else {
  11.                 long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
  12.                 if (ifModifiedSince < (lastModified / 1000 * 1000)) {
  13.                     // If the servlet mod time is later, call doGet()
  14.                     // Round down to the nearest second for a proper compare
  15.                     // A ifModifiedSince of -1 will always be less
  16.                     maybeSetLastModified(resp, lastModified);
  17.                     doGet(req, resp);
  18.                 } else {
  19.                     resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
  20.                 }
  21.             }

  22.         } else if (method.equals(METHOD_HEAD)) {
  23.             long lastModified = getLastModified(req);
  24.             maybeSetLastModified(resp, lastModified);
  25.             doHead(req, resp);

  26.         } else if (method.equals(METHOD_POST)) {
  27.             doPost(req, resp);
  28.             
  29.         } else if (method.equals(METHOD_PUT)) {
  30.             doPut(req, resp);
  31.             
  32.         } else if (method.equals(METHOD_DELETE)) {
  33.             doDelete(req, resp);
  34.             
  35.         } else if (method.equals(METHOD_OPTIONS)) {
  36.             doOptions(req,resp);
  37.             
  38.         } else if (method.equals(METHOD_TRACE)) {
  39.             doTrace(req,resp);
  40.             
  41.         } else {
  42.             //
  43.             // Note that this means NO servlet supports whatever
  44.             // method was requested, anywhere on this server.
  45.             //

  46.             String errMsg = lStrings.getString("http.method_not_implemented");
  47.             Object[] errArgs = new Object[1];
  48.             errArgs[0] = method;
  49.             errMsg = MessageFormat.format(errMsg, errArgs);
  50.             
  51.             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
  52.         }
  53.     }

  这里涉及到两个角色:


  抽象模板(Abstract Template)角色有如下责任:


  ■  定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。


  ■  定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。


  具体模板(Concrete Template)角色又如下责任:


  ■  实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。


  ■  每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同




阅读(599) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~