介绍:模板模式定义了一个模板抽象类,这个抽象类中定义了方法调用的形式,顺序。子类通过重写对方法进行实现,但是调用方式不能改变。

模板模式中的模板中定义了核心的代码骨架,一些有着不同方式实现的代码放在子类中,模板模式规定了方法执行的方式或者可以说是方法的执行顺序,执行结构,使得子类只能遵守这些规定。

模板模式解决了很多代码在子类中通用。每次业务相同的代码,用户每次还要重写这些一样的代码,现在将这些通用的代码提取出来,放在一个抽象类中,在抽象类中规定方法执行的方式,一些具体实现不一样的方法定义为抽象方法,由子类通过继承抽象类实现这些抽象方法。也可以说是把通用的算法抽象出来。

把固定的部分封装起来,对于可变的部分用户可以进行扩展,提取出代码的公共部分放在父类,行为由父类控制,子类负责实现可变的部分。

在tomcat中就有模板模式的应用,在用户写的Servlet中的doget和dopost方法就是子类中重写的方法,HttpServlet中的service方法定义了方法执行的方式,以下是HttpServlet中service方法的源码,方法中定义了每个方法执行的顺序,方式。也就是规定了核心,用户需要对那些服务定义自己的代码。

  1. protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  2. String method = req.getMethod();
  3. long lastModified;
  4. if (method.equals("GET")) {
  5. lastModified = this.getLastModified(req);
  6. if (lastModified == -1L) {
  7. this.doGet(req, resp);
  8. } else {
  9. long ifModifiedSince;
  10. try {
  11. ifModifiedSince = req.getDateHeader("If-Modified-Since");
  12. } catch (IllegalArgumentException var9) {
  13. ifModifiedSince = -1L;
  14. }
  15.  
  16. if (ifModifiedSince < lastModified / 1000L * 1000L) {
  17. this.maybeSetLastModified(resp, lastModified);
  18. this.doGet(req, resp);
  19. } else {
  20. resp.setStatus(304);
  21. }
  22. }
  23. } else if (method.equals("HEAD")) {
  24. lastModified = this.getLastModified(req);
  25. this.maybeSetLastModified(resp, lastModified);
  26. this.doHead(req, resp);
  27. } else if (method.equals("POST")) {
  28. this.doPost(req, resp);
  29. } else if (method.equals("PUT")) {
  30. this.doPut(req, resp);
  31. } else if (method.equals("DELETE")) {
  32. this.doDelete(req, resp);
  33. } else if (method.equals("OPTIONS")) {
  34. this.doOptions(req, resp);
  35. } else if (method.equals("TRACE")) {
  36. this.doTrace(req, resp);
  37. } else {
  38. String errMsg = lStrings.getString("http.method_not_implemented");
  39. Object[] errArgs = new Object[]{method};
  40. errMsg = MessageFormat.format(errMsg, errArgs);
  41. resp.sendError(501, errMsg);
  42. }
  43.  
  44. }

假设我们去了饭店,干什么,当然是去吃饭喽,我们到饭店吃饭得有个流程吧,首先我们到了饭店,饭店需要为你找座位吧,当你坐下之后,服务员给你一张菜单,让你点菜,这都是固定的顺序,但是你点什么菜不是饭店规定好的,可以随意点,点完之后服务员会把点的这些菜提交给后厨,后厨做好之后服务员端上来,吃完之后就要到前台结账买单。除了顾客点菜之外,剩下的步骤都是一套固定的流程,我们就可以定义一个模板类,规定好饭店的这些流程,只有点餐这个流程不需要具体规定,留给顾客自己选择。

定义模板类:饭店中时规定了方法执行的流程和具体操作,但是顾客点菜是顾客自己的行为,不需要规定

  1. package demo_template;
  2.  
  3. public abstract class Template {
  4.  
  5. //服务员为顾客选择座位
  6. private void selectSeat() {
  7. System.out.println("选择一个座位");
  8. }
  9.  
  10. //服务员给顾客菜单
  11. private void passMenu() {
  12. System.out.println("递菜单");
  13. }
  14.  
  15. //假设顾客只点了A,B,C三个菜
  16. public abstract void selectA();
  17.  
  18. public abstract void selectB();
  19.  
  20. public abstract void selectC();
  21.  
  22. //服务员提交菜单
  23. private void submitMenu() {
  24. System.out.println("提交菜单");
  25. }
  26.  
  27. //上菜
  28. private void serving() {
  29. System.out.println("上菜");
  30. }
  31. //顾客买单
  32. private void pay() {
  33. System.out.println("顾客买单");
  34. }
  35.  
  36. protected void service() {
  37. selectSeat();
  38. passMenu();
  39. this.selectA();
  40. this.selectB();
  41. this.selectC();
  42. submitMenu();
  43. serving();
  44. pay();
  45.  
  46. }
  47.  
  48. }

定义第一个顾客:顾客只负责点菜,其他不需要关心

  1. package demo_template;
  2.  
  3. public class First extends Template {
  4.  
  5. @Override
  6. public void selectA() {
  7. System.out.println("地三鲜");
  8. }
  9.  
  10. @Override
  11. public void selectB() {
  12. System.out.println("大米饭");
  13. }
  14.  
  15. @Override
  16. public void selectC() {
  17. System.out.println("橙汁");
  18. }
  19. }

第二位顾客:

  1. package demo_template;
  2.  
  3. public class Second extends Template {
  4. @Override
  5. public void selectA() {
  6. System.out.println("大米饭");
  7. }
  8.  
  9. @Override
  10. public void selectB() {
  11. System.out.println("糖醋鲤鱼");
  12. }
  13.  
  14. @Override
  15. public void selectC() {
  16. System.out.println("地三鲜");
  17. }
  18. }

测试类:

  1. package demo_template;
  2.  
  3. public class Test {
  4.  
  5. public static void main(String[] args) {
  6. System.out.println("第一位顾客:");
  7. Template first = new First();
  8. first.service();
  9. System.out.println("---------------------");
  10. System.out.println("第二位顾客:");
  11. Template second = new Second();
  12. second.service();
  13. }
  14. }

测试类用到了多态,我们创建的对象是First和Second的,类型是Template的,模板类中的三个点菜方法是用的this调用,this代表当前对象,当前对象是谁的,当然是First和Second的。

输出:

  1. 第一位顾客:
  2. 选择一个座位
  3. 递菜单
  4. 地三鲜
  5. 大米饭
  6. 橙汁
  7. 提交菜单
  8. 上菜
  9. 顾客买单
  10. ---------------------
  11. 第二位顾客:
  12. 选择一个座位
  13. 递菜单
  14. 大米饭
  15. 糖醋鲤鱼
  16. 地三鲜
  17. 提交菜单
  18. 上菜
  19. 顾客买单

优点:

1、封装不变部分,扩展可变部分。

2、提取公共代码,便于维护。

3、行为由父类控制,子类实现。

缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

使用场景:

1、有多个子类共有的方法,且逻辑相同。

2、重要的、复杂的方法,可以考虑作为模板方法。

参考:

http://blog.csdn.net/lovelion/article/details/8299794

http://www.runoob.com/design-pattern/template-pattern.html

Java设计模式-模板模式的更多相关文章

  1. 【设计模式】Java设计模式 - 模板模式

    Java设计模式 - 模板模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  2. 3.java设计模式-建造者模式

    Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...

  3. 12. 星际争霸之php设计模式--模板模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  4. Java设计模式——组合模式

    JAVA 设计模式 组合模式 用途 组合模式 (Component) 将对象组合成树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有唯一性. 组合模式是一种结构型模 ...

  5. java设计模式--单列模式

    java设计模式--单列模式 单列模式定义:确保一个类只有一个实例,并提供一个全局访问点. 下面是几种实现单列模式的Demo,每个Demo都有自己的优缺点: Demo1: /** * 单列模式需要满足 ...

  6. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  7. Java设计模式——外观模式

    JAVA 设计模式 外观模式 用途 外观模式 (Facade) 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 外观模式是一种结构型模式. 结构

  8. 【设计模式】Java设计模式 -工厂模式

    [设计模式]Java设计模式 -工厂模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! 目 ...

  9. 【设计模式】Java设计模式 - 原型模式

    [设计模式]Java设计模式 - 原型模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起 ...

随机推荐

  1. CEPH RGW 设置 user default_placement为ssd-placement,优化100KB-200KB小文件性能,使用户创建的bucket对象放置到 SSD设备的Pool上。

    sudo radosgw-admin metadata get user:tuanzi > user.md.json vi user.md.json #to add ssd-placement ...

  2. Qemu,KVM,Virsh傻傻的分不清

    当你安装了一台Linux,想启动一个KVM虚拟机的时候,你会发现需要安装不同的软件,启动虚拟机的时候,有多种方法: virsh start kvm命令 qemu命令 qemu-kvm命令 qemu-s ...

  3. ERROR 1045 (28000): Access denied for user xxx & ERROR 1449 (HY000): The user specified as a definer xxx does not exists

    今天在一个修改过权限的MySQL数据库遇到了"ERROR 1045 (28000): Access denied for user 'xxx'@'xxx.xxx.xxx.xxx' (usin ...

  4. Linux如何查找处理文件名后包含空格的文件

    Linux如何查找处理文件名后包含空格的文件   当Linux下文件名中出现空格这类特殊情况话,如何查找或确认那些文件名后有空格呢? 又怎么批量替换处理掉这些空格呢? 方法1: 输入文件名后使用Tab ...

  5. 安装Apache提示APR not found的解决办法

    不知道为什么在安装apache2.2.22版本的时候没有任何问题,直接使用命令 ./configure --prefix=/home/www/www_test/software/apache-2.2. ...

  6. 打开CSDN论坛出现403

    打开CSDN论坛出现403 在查找资料的过程中,出现"403-禁止访问"

  7. Flex中对表格中某列的值进行数字格式化并求百分比

    1.问题背景 一般的,需要对表格中某列的数值进行格式化,对该数值乘以100,并保留两位小数,添加"%" 2.实现实例 <?xml version="1.0" ...

  8. 常用的freemark语法(三)

    一,符号的意义 1.0,单问号 ?后面要加关键字,例如:<#if object?exists>object对象不为空</#if> <#if str??>${str? ...

  9. C#图解教程 第十八章 枚举器和迭代器

    枚举器和迭代器 枚举器和可枚举类型 foreach语句 IEnumerator接口 使用IEnumerable和IEnumerator的示例 泛型枚举接口迭代器 迭代器块使用迭代器来创建枚举器使用迭代 ...

  10. day9(Hash、字典)

    一.Hash 简介: Hash,一般被翻译成"散列",也有直接音译"哈希"的,就是把任意长度的输入,通过哈希算法,变换成固定长度的输出,输出的结果就叫做哈希值, ...