实例讲解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 模板方法模式的资料请关注我们其它相关文章!

时间: 2020-06-23

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

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

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

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

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

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

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

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

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

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

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

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

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

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

详解C#设计模式编程中的模板方法模式使用

一.引言 提到模板,大家肯定不免想到生活中的"简历模板"."论文模板"."Word中模版文件"等,在现实生活中,模板的概念就是--有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简历模板,下载下来的简历模板的格式都是相同的,然而我们下载下来简历模板之后我们可以根据自己的情况填充不同的内容要完成属于自己的简历.在设计模式中,模板方法模式中模板和生活中模板概念非常类似,下面让我们就详细介绍模板方法的定义,大家可以根据生活中模板的概

深入解析Java的设计模式编程中建造者模式的运用

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 类型:创建类模式 类图: 四个要素 产品类:一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量.在本类图中,产品类是一个具体的类,而非抽象类.实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成. 抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现.这样更容易扩展.一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回

举例解析Java的设计模式编程中里氏替换原则的意义

里氏替换原则,OCP作为OO的高层原则,主张使用"抽象(Abstraction)"和"多态(Polymorphism)"将设计中的静态结构改为动态结构,维持设计的封闭性."抽象"是语言提供的功能."多态"由继承语义实现. 里氏替换原则包含以下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的设计模式编程中的原型模式

定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 类型:创建类模式 类图: 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype.Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法.在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedExcepti

深入解析Java的设计模式编程中单例模式的使用

定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 类型:创建类模式 类图: 类图知识点: 1.类图分为三部分,依次是类名.属性.方法 2.以<<开头和以>>结尾的为注释信息 3.修饰符+代表public,-代表private,#代表protected,什么都没有代表包可见. 4.带下划线的属性或方法代表是静态的. 5.对类图中对象的关系不熟悉的朋友可以参考文章:设计模式中类的关系. 单例模式应该是23种设计模式中最简单的一种模式了.它有以下几个要素: 私有的构

对比Java设计模式编程中的状态模式和策略模式

为了能在Java应用程序中正确的使用状态模式和策略模式,开发人员需要清楚地知道这两种模式之间的区别.尽管状态模式和策略模式的结构非常相似,它们又同样遵循开闭原则,都代表着SOLID设计原则的'O',但它们的意图是完全不同的.Java中的策略模式是对一组相关的算法进行封装,给调用方提供了运行时的灵活性.调用方可以在运行时选择不同的算法,而不用修改使用策略的那个Context类.使用策略模式的经典例子包括实现加密算法,压缩算法,以及排序算法.另一方面,状态模式使用一个对象可以在不同的状态下表现出不同

详解Java设计模式编程中的策略模式

定义:定义一组算法,将每个算法都封装起来,并且使他们之间可以互换. 类型:行为类模式 类图: 策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换.在前面说过的行为类模式中,有一种模式也是关注对算法的封装--模版方法模式,对照类图可以看到,策略模式与模版方法模式的区别仅仅是多了一个单独的封装类Context,它与模版方法模式的区别在于:在模版方法模式中,调用算法的主体在抽象的父类中,而在策略模式中,调用算法的主体则是封装到了封装类Context中

解析Java的JNI编程中的对象引用与内存泄漏问题

JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互--在 Java 程序中调用 native code:在 native code 中嵌入 Java 虚拟机调用 Java 的代码. JNI 编程在软件开发中运用广泛,其优势可以归结为以下几点: 利用 native code 的平台相关性,在平台相关的编程中彰显优势. 对 native code 的代码重用. native code 底层操作