实例讲解JAVA 模板方法模式

在讲述这个模式之前,我们先看一个案例:抄题目:两个学生将老师出的题目抄写在纸上,并且写出答案

先看一个比较笨的写法

public class TestPaperA {
 public void testQuestion1(){
  System.out.println("1+1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:b");
 }

 public void testQuestion2(){
  System.out.println("1*1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:a");
 }

 public void testQuestion3(){
  System.out.println("1/1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:a");
 }
}

public class TestPaperB {
 public void testQuestion1(){
  System.out.println("1+1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:c");
 }

 public void testQuestion2(){
  System.out.println("1*1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:a");
 }

 public void testQuestion3(){
  System.out.println("1/1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:d");
 }
}

public class Test {
 public static void main(String[] args) {
  System.out.println("学生甲抄的试卷:");
  TestPaperA studentA= new TestPaperA();
  studentA.testQuestion1();
  studentA.testQuestion2();
  studentA.testQuestion3();

  System.out.println("学生乙抄的试卷:");
  TestPaperB studentB= new TestPaperB();
  studentB.testQuestion1();
  studentB.testQuestion2();
  studentB.testQuestion3();
 }
}

输出结果:

学生甲抄的试卷:
1+1等于几? a.1 b.2 c.3 d.4
答案:b
1*1等于几? a.1 b.2 c.3 d.4
答案:a
1/1等于几? a.1 b.2 c.3 d.4
答案:a
学生乙抄的试卷:
1+1等于几? a.1 b.2 c.3 d.4
答案:c
1*1等于几? a.1 b.2 c.3 d.4
答案:a
1/1等于几? a.1 b.2 c.3 d.4
答案:d

可以看出,学生甲和学生乙除了答案不一样,抄的题目都一样,抄题目的过程容易出错,而且如果老师改了题目,那么两个学生都需要把题目改掉

怎么优化?我们先来一个初步优化:学过继承的都会想到,把公共部分放到父类中,子类继承父类后,自然就拥有了公共部分

public class TestPaper {
 public void testQuestion1(){
  System.out.println("1+1等于几? a.1 b.2  c.3 d.4");
 }

 public void testQuestion2(){
  System.out.println("1*1等于几? a.1 b.2  c.3 d.4");
 }

 public void testQuestion3(){
  System.out.println("1/1等于几? a.1 b.2  c.3 d.4");
 }
}

public class TestPaperA extends TestPaper{
 @Override
 public void testQuestion1(){
  super.testQuestion1();
  System.out.println("答案:b");
 }
 @Override
 public void testQuestion2(){
  super.testQuestion2();
  System.out.println("答案:a");
 }
 @Override
 public void testQuestion3(){
  super.testQuestion3();
  System.out.println("答案:a");
 }
}

public class TestPaperB extends TestPaper{
 @Override
 public void testQuestion1(){
  super.testQuestion1();
  System.out.println("答案:c");
 }
 @Override
 public void testQuestion2(){
  super.testQuestion2();
  System.out.println("答案:a");
 }
 @Override
 public void testQuestion3(){
  super.testQuestion3();
  System.out.println("答案:d");
 }
}

测试类同上

我们看这个初步优化,发现还是有重复的部分,比如super.testQuestion1()和System.out.println("答案”)

我们既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复。

对于“抄题目”这个例子来说,除了学生的答案会有不同的结果,其他全部都是一样的。继续优化:

public abstract class TestPaper {
 public void testQuestion1(){
  System.out.println("1+1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:"+answer1());
 }

 public void testQuestion2(){
  System.out.println("1*1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:"+answer2());
 }

 public void testQuestion3(){
  System.out.println("1/1等于几? a.1 b.2  c.3 d.4");
  System.out.println("答案:"+answer3());
 }

 public abstract String answer1();

 public abstract String answer2();

 public abstract String answer3();
}

public class TestPaperA extends TestPaper{
 @Override
 public String answer1() {
  return "b";
 }
 @Override
 public String answer2() {
  return "a";
 }
 @Override
 public String answer3() {
  return "a";
 }
}

public class TestPaperB extends TestPaper{
 @Override
 public String answer1() {
  return "c";
 }
 @Override
 public String answer2() {
  return "a";
 }
 @Override
 public String answer3() {
  return "d";
 }
}

public class Test {
 public static void main(String[] args) {
  System.out.println("学生甲抄的试卷:");
  TestPaper studentA= new TestPaperA();
  studentA.testQuestion1();
  studentA.testQuestion2();
  studentA.testQuestion3();

  System.out.println("学生乙抄的试卷:");
  TestPaper studentB= new TestPaperB();
  studentB.testQuestion1();
  studentB.testQuestion2();
  studentB.testQuestion3();
 }
}

输出结果:

学生甲抄的试卷:
1+1等于几? a.1 b.2 c.3 d.4
答案:b
1*1等于几? a.1 b.2 c.3 d.4
答案:a
1/1等于几? a.1 b.2 c.3 d.4
答案:a
学生乙抄的试卷:
1+1等于几? a.1 b.2 c.3 d.4
答案:c
1*1等于几? a.1 b.2 c.3 d.4
答案:a
1/1等于几? a.1 b.2 c.3 d.4
答案:d

结果和之前一模一样,但简洁了很多。此时要有更多的学生来答卷,只不过是在试卷的木板上填写选择题的选项答案,这是每个人的试卷唯一不同(谁说的,名字也不同,但这样的做法的确是对试卷的最大复用)

下面介绍模板方法模式:https://www.jb51.net/article/189195.htm

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

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

public abstract class AbstractClass {
 //一些抽象行为,放到子类去实现
 public abstract void primitiveOperation1();
 public abstract void primitiveOperation2();

 //模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们都推迟到子类去实现
 public void templateMethod(){
  primitiveOperation1();
  primitiveOperation2();
 }
}

ConcreteClass实现父类所定义的一个或多个抽象方法。每一个AbstractClass都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

public class ConcreteClassA extends AbstractClass{
 @Override
 public void primitiveOperation1() {
  //具体类A方法1实现,与ConcreteClassB不同的方法实现
 }

 @Override
 public void primitiveOperation2() {
  //具体类A方法2实现,与ConcreteClassB不同的方法实现
 }
}

public class ConcreteClassB extends AbstractClass{
 @Override
 public void primitiveOperation1() {
  //具体类B方法1实现,与ConcreteClassA不同的方法实现
 }

 @Override
 public void primitiveOperation2() {
  //具体类B方法2实现,与ConcreteClassA不同的方法实现
 }
}

测试代码

public class Test {
 public static void main(String[] args) {
  AbstractClass c = null;

  c = new ConcreteClassA();
  c.templateMethod();

  c = new ConcreteClassB();
  c.templateMethod();
 }
}

模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。

模板方法模式就是提供了一个很好的代码复用平台。因为有时候,我们会遇到由一系列步骤构成的过程需要执行。这个过程从高层次上看是相同的,但有些步骤的实现可能不同。这时候,我们通常就应该要考虑用模板方法模式了。

当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠

以上就是实例讲解JAVA 模板方法模式的详细内容,更多关于JAVA 模板方法模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • 举例讲解Java设计模式编程中模板方法模式的运用实例

    模板方法模式定义为: 在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中去实现.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某一些步骤. 模板方法在基类中定义了一个操作的流程顺序,能够保证该步骤按序进行,有一些步骤的具体实现在基类中已经声明,而将一些变化的步骤的具体实现交给了子类去实现,从而就达到了延迟一些步骤到子类中,模板方法一个最大的好处就是能够设定一个业务流程能够按照一定严格的顺序执行,控制了整个算法的执行步骤. 这个方法将算法定义成一组步骤,其中凡是想让

  • Java设计模式模板方法(Template)原理解析

    这篇文章主要介绍了Java设计模式模板方法(Template)原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言: 我们在开发中有很多固定的流程,这些流程有很多步凑是固定的,比如JDBC中获取连接,关闭连接这些流程是固定不变的,变动的只有设置参数,解析结果集这些是根据不同的实体对象"来做调整",针对这种拥有固定算法流程,其中有固定的步凑,存在不固定的步凑的情况下就诞生了模板方法模式. 模板方法模式(Template)定义:

  • java设计模式之模板方法模式详解

    一.什么是模板方法模式 概念:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 通俗的讲,模板方法模式是通过把不变行为搬到超类,去除子类里面的重复代码提现它的优势,它提供了一个很好的代码复用平台.当不可变和可变的方法在子类中混合在一起的时候,不变的方法就会在子类中多次出现,这样如果摸个方法需要修改则需要修改很多个,虽然这个这个问题在设计之初就应该想好.这个时候模板方法模式就起到了作用了,通过模板方法模式把这些重复出现的

  • Java设计模式模板方法模式(Template)用法解析

    这篇文章主要介绍了Java设计模式模板方法模式(Template)用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言: 我们在开发中有很多固定的流程,这些流程有很多步凑是固定的,比如JDBC中获取连接,关闭连接这些流程是固定不变的,变动的只有设置参数,解析结果集这些是根据不同的实体对象"来做调整",针对这种拥有固定算法流程,其中有固定的步凑,存在不固定的步凑的情况下就诞生了模板方法模式. 模板方法模式(Template)定义

  • Java经典设计模式之模板方法模式定义与用法示例

    本文实例讲述了Java设计模式之模板方法模式.分享给大家供大家参考,具体如下: 我们在生活中,很多事情都包含特定的一些步骤.如去银行办理业务,通常步骤的次序是:取号 –> 填单 –> 等待叫号–>办理业务.这几个步骤中,有的是不变的,比如取号,每个人都要取,但有的是要变的,比如都有填单,但是根据不同的业务,填写的单据不同.又比如我们外出吃饭,一般的步骤是:点餐–>等待–>吃饭–>付钱,也能发现同样的规律.这样的事情数不胜数. 项目开发中,也可能遇到这样的情况,多个功能模

  • 详解JAVA设计模式之模板模式

    在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计模式属于行为型模式. 介绍 意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 主要解决:一些方法通用,却在每一个子类都重新写了这一方法. 何时使用:有一些通用的方法. 如何解决:将这些通用算法抽象出来. 关键代码:在抽象类实现,其他步骤在子

  • 深入解析Java的设计模式编程中的模板方法模式

    定义:  定义一个操作中的算法的框架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 听起来好高端的样子,我的理解: 1.父类声明了若干个抽象方法(基本方法)和若干个具体方法(模板方法) 2.抽象方法是一个算法(过程)的步骤,在子类中实现 3.模板方法是一个算法(过程)的框架,在父类中已经约定好,实现对基本方法调用,完成固定的逻辑 4.一个算法(过程)的结构在父类中定义,具体的实现细节则在子类中实现 注:为了防止恶意操作,一般模板方法都加上final

  • 实例讲解JAVA 模板方法模式

    在讲述这个模式之前,我们先看一个案例:抄题目:两个学生将老师出的题目抄写在纸上,并且写出答案 先看一个比较笨的写法 public class TestPaperA { public void testQuestion1(){ System.out.println("1+1等于几? a.1 b.2 c.3 d.4"); System.out.println("答案:b"); } public void testQuestion2(){ System.out.print

  • 实例讲解JAVA设计模式之备忘录模式

    在讲述这个模式之前,我们先看一个案例:游戏回档 游戏的某个场景,一游戏角色有生命力.攻击力.防御力等数据,在打Boss前和后会不一样,我们允许玩家如果感觉与Boss决斗的效果不理想,可以让游戏恢复到决斗前.下面是代码: 游戏角色类,用来存储角色的生命力.攻击力.防御力的数据. public class GameRole { private int vit;//生命力 private int atk;//攻击力 private int def;//防御力 //状态显示 public void st

  • 实例讲解JAVA 适配器模式

    在讲述这个模式之前,我们先看一个案例:中国球员去NBA打篮球 中国球员去NBA打篮球,可是他不懂英语,所以听不懂教练安排的战术,所以现在有三种解决方式 1.球员学会英语.2.教练学会中文.3.请个翻译. 1和2是长久之计,但不能解决迫在眉睫的问题.请个翻译是短暂的更好的选择. 放在软件设计层面上,这就叫做适配器模式.https://www.jb51.net/article/189484.htm 将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以

  • 实例讲解Java HashSet

    HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合. HashSet 允许有 null 值. HashSet 是无序的,即不会记录插入的顺序. HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的. 您必须在多线程访问时显式同步对 HashSet 的并发访问. HashSet 实现来 Set 接口. HashSet 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类. 基本类型对应的包装类表如下: 基本类型 引用类型

  • 实例讲解Java中的synchronized

    一.使用场景 在负责后台开发的时候,很多时候都是提供接口给前端开发人员去调用,会遇到这样的场景: 需要提供一个领奖接口,每个用户名只能领取一次,我们可以将成功领取的用户在数据库用个标记保存起来.如果这个用户再来领取的时候,查询数据库看该用户是否领取过. 但是问题来了,假设用户手速很快,极短时间内点了两次领奖按钮(前端没有进行控制,我们也不能依赖前端去控制).那么可能掉了两次领奖接口,而且有可能第二次调用的时候查询数据库的时候,第一次领奖还没有执行完成更新领奖标记. 这种场景就可以使用到synch

  • 实例讲解Java 自旋锁

    一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下: 所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是AtomicInteger中的一个updateAndGet方法,下图所示(当然也可以直接看unsafe类中的getAndAddInt等类似方法): 我们可以看出在while循环中使用CAS去尝试更新一个变量,如果更新失败,就会一直在这个循环中一直在尝试

  • Java设计模式之java模板方法模式详解

    目录 模板方法模式 介绍 角色 代码演示 模板方法模式总结 优点 缺点 适用场景 源码分析模板方法模式的典型应用 Servlet 中的模板方法模式 Hello World! Spring中的IOC容器启动-refresh()方法 参考文章 总结 模板方法模式 在程序开发中,经常会遇到这种情况:某个方法要实现的算法需要多个步骤,但其中有一些步骤是固定不变的,而另一些步骤则是不固定的.为了提高代码的可扩展性和可维护性,模板方法模式在这种场景下就派上了用场. 譬如制作一节网课的步骤可以简化为4个步骤:

  • 实例讲解Java的设计模式编程中责任链模式的运用

    定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止. 类型:行为类模式 类图: 首先来看一段代码: public void test(int i, Request request){ if(i==1){ Handler1.response(request); }else if(i == 2){ Handler2.response(request); }else if(i == 3){ Handler3

  • 实例讲解Java设计模式编程中如何运用代理模式

    定义:  Provide a surrogate or placeholder for another object to control access to it. 为其他对象一种代理以控制对这个对象的访问. 一般描述: 一般包含的三个角色:抽象主题.具体主题.代理主题. 抽象主题:是一个抽象类或接口,是一个普通的业务类型定义. 具体主题:业务逻辑的具体执行者 代理角色:负责对真是角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现. 通用类图: 通用代码: package Pro

  • 实例讲解Java的Spring框架中的控制反转和依赖注入

    近来总是接触到 IoC(Inversion of Control,控制反转).DI(Dependency Injection,依赖注入)等编程原则或者模式,而这些是著名 Java 框架 Spring.Struts 等的核心所在.针对此查了 Wikipedia 中各个条目,并从图书馆借来相关书籍,阅读后有些理解,现结合书中的讲解以及自己的加工整理如下: eg1 问题描述: 开发一个能够按照不同要求生成Excel或 PDF 格式的报表的系统,例如日报表.月报表等等.   解决方案: 根据"面向接口编

随机推荐