模板方法模式

模式定义

         所谓模板方法模式就是在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

          模板方法模式是基于继承的代码复用技术的。在模板方法模式中,我们可以将相同部分的代码放在父类中,而不同的代码放入不同的子类中。也就是说我们需要声明一个抽象的父类,将部分逻辑以具体方法以及具体构造函数形式实现,然后声明一些抽象方法让子类来实现剩余的逻辑,不同的子类可以以不同的方式来实现这些逻辑。

          其实所谓模板就是一个方法,这个方法将算法的实现定义成了一组步骤,其中任何步骤都是可以抽象的,交由类来负责实现。这样就可以保证算法的结构保持不变,同时由子类提供部分实现。

          模板是一个方法,那么他与普通的方法存在什么不同呢?模板方法是定义在抽象类中,把基本操作方法组合在起形成一个总算法或者一组步骤的方法。而普通的方法是实现各个步骤的方法,我们可以认为普通方法是模板方法一个组成部分。


模式结构


模式实现

加入一个场景,”小时候,数学老师的随堂测试,都是在黑板上抄题,要我们抄题目,然后在做答案,那个时候假如你已经近视了,刚好那天你没带眼镜,所以有时候会抄错题目,比如把3看成8,7看成1,那就意味着你做的再好,也不会正确。惨了。。。“

这其实就是一个典型的模板方法模式

AbstractClass

package com.bjsxt.templatemethod.over;

abstract class TestPaper {

	public abstract String Answer1(); 
	public abstract String Answer2();
	public abstract String Answer3();
	public void testQuestion1(){
		System.out.println("1 + 0 = A 1  B 2  C 3" + "答案:" + Answer1() );
	}
	public void testQuestion2(){
		System.out.println("1 + 1 = A 1  B 2  C 3" + "答案:" + Answer2() );
	}
	public void testQuestion3(){
		System.out.println("1 + 2 = A 1  B 2  C 3" + "答案:" + Answer3() );
	}
	public void result(){
		testQuestion1();
		testQuestion2();
		testQuestion3();
	}
}

ConcreteClass

package com.bjsxt.templatemethod.over;

public class TestPaperA extends TestPaper {

	public String Answer1() {
		return "A";
	}

	public String Answer2() {
		return "B";
	}

	public String Answer3() {
		return "C";
	}
}

package com.bjsxt.templatemethod.over;

public class TestPaperB extends TestPaper {

	public String Answer1() {
		return "B";
	}

	public String Answer2() {
		return "A";
	}

	public String Answer3() {
		return "C";
	}
}

Client

package com.bjsxt.templatemethod.over;

public class Client {

	public static void main(String[] args) {
		TestPaper testPaperA = new TestPaperA();
		TestPaper testPaperB = new TestPaperB();
		System.out.println("the result of testPaperA");
		testPaperA.result();
		System.out.println("the result of testPaperB");
		testPaperB.result();
	}
}

     从上面的运行结果可以看出,我们的模板方法模式表现的非常良好,但是我们似乎忽略了一些东西?如果有一些学生选择不做一些题呢,但是每次我们必须填写答案,那末怎么解决这个问题呢

          遇到这个问题我们可以使用钩子。所谓钩子就是一种被声明在抽象类中的方法,但只有空的或者默认的实现。子的存在可以使子类能够对算法的不同点进行挂钩,即让子类能够对模板方法中某些即将发生变化的步骤做出相应反应。当然要不要挂钩,由子类决定。


对于上述要求我们可以做出如下改进

AbstractClass

package com.bjsxt.templatemethod;

abstract class TestPaper {

	public abstract String Answer1(); 
	public abstract String Answer2();
	public abstract String Answer3();
	public void testQuestion1(){
		System.out.println("1 + 0 = A 1  B 2  C 3" + "答案:" + Answer1() );
	}
	public void testQuestion2(){
		System.out.println("1 + 1 = A 1  B 2  C 3" + "答案:" + Answer2() );
	}
	public void testQuestion3(){
		System.out.println("1 + 2 = A 1  B 2  C 3" + "答案:" + Answer3() );
	}
	public void result(){
		testQuestion1();
		testQuestion2();
		if(wantSolve()){
			testQuestion3();
		}
	}
	public boolean wantSolve(){
		return true;
	}
}

ConcreteClass

package com.bjsxt.templatemethod;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

public class TestPaperA extends TestPaper {

	public String Answer1() {
		return "A";
	}

	public String Answer2() {
		return "B";
	}

	public String Answer3() {
		return "C";
	}

	public boolean wantSolve() {
		if("y".equals(getStudentInput().toLowerCase()))
			return true;
		return false;
	}
	public String getStudentInput(){
		String result = null;
		System.out.println("would you want to solve the question? please input y or n");
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			result = in.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if(result == null)	result = "n";
		return result;
	}
}


package com.bjsxt.templatemethod;

public class TestPaperB extends TestPaper {

	public String Answer1() {
		return "B";
	}

	public String Answer2() {
		return "A";
	}

	public String Answer3() {
		return "C";
	}
}

Client


package com.bjsxt.templatemethod;

public class Client {

	public static void main(String[] args) {
		TestPaper testPaperA = new TestPaperA();
		TestPaper testPaperB = new TestPaperB();
		System.out.println("the result of testPaperA");
		testPaperA.result();
		System.out.println("the result of testPaperB");
		testPaperB.result();
	}
}

模式优缺点

         优点

              1、模板方法模式在定义了一组算法,将具体的实现交由子类负责。

              2、模板方法模式是一种代码复用的基本技术。

              3、模板方法模式导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。

          缺点

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

使用场景

             个子类中公共的行为被提取到超类中,避免了代码的重复。


模式总结

            模式方法为我们定义了整体的代码框架,对于差别延迟到子类来实现。很好的解决代码重复的问题,代代码重构,使代码变的更加整洁。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值