23个java设计模式(十八)-- 模板方法模式

2016年03月24日 原创
关键词: java 设计模式
摘要 模板方法模式定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

一、概述。

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

类中的方法用以表明该类的实例所具有的行为,一个类可以有许多方法,而且类中的实例方法也可以调用该类中的其他若干个方法。在编写类的时候,可能需要将类的许多方法集成到一个实例方法中,即用一个实例方法封装若干个方法的调用,以此表示一个算法的骨架,也就是说,调用该实例方法相当于按着一定顺序执行若干个方法。

模板方法是关于怎样将若干个方法集成到一个方法中,以便形成一个解决问题的算法骨架。模板方法模式的关键是在一个抽象类中定义一个算法的骨架,即将若干个方法集成到一个方法中,并称该方法为一个模板方法。

二、模板方法模式的结构。

模板方法模式包括两种角色:

  • 抽象模板(Abstract Template):抽象模板是一个抽象类。抽象模板定义了若干个方法以表示一个算法的各个步骤,这些方法中有抽象方法也有非抽象方法,其中的抽象方法称作原语操作(Primitive Operation)。重要的一点是,抽象模板中还定义了一个称作模板方法的方法,该方法不仅包含抽象模板中表示算法步骤的方法调用,而且也可以包含定义在抽象模板中的其他对象的方法调用,即模板方法定义了算法的骨架。
  • 具体模板(Concrete Template):具体模板是抽象模板的子类,实现抽象模板中的原语操作。

三、示例程序。

抽象模板(Abstract Template)

AbstractTemplate.java

public abstract class AbstractTemplate {
	protected File[] allFiles;
	protected File dir;
	public AbstractTemplate(File dir) {
		this.dir = dir;
	}
	public final void showFileName() {
		allFiles = dir.listFiles();
		sort();
		printFiles();
	}
	public abstract void sort();
	public abstract void printFiles();
}

具体模板(Concrete Template)

ConcreteTemplate1.java

public class ConcreteTemplate1 extends AbstractTemplate{

	public ConcreteTemplate1(File dir) {
		super(dir);
	}

	@Override
	public void sort() {
		for(int i = 0; i < allFiles.length; i++) {
			for(int j = i+1; j < allFiles.length; j++) {
				if(allFiles[j].lastModified()<allFiles[i].lastModified()) {
					File file = allFiles[j];
					allFiles[j] = allFiles[i];
					allFiles[i] = file;
				}
			}
		}
	}

	@Override
	public void printFiles() {
		for(int i = 0; i < allFiles.length; i++) {
			long time = allFiles[i].lastModified();
			Date date = new Date(time);
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String str = format.format(date);
			String name = allFiles[i].getName();
			System.out.println((i+1)+" : "+name+"("+str+")");
		}
	}

}

ConcreteTemplate2.java

public class ConcreteTemplate2 extends AbstractTemplate{

	public ConcreteTemplate2(File dir) {
		super(dir);
	}

	@Override
	public void sort() {
		for(int i = 0; i < allFiles.length; i++) {
			for(int j = i+1; j<allFiles.length; j++) {
				if(allFiles[j].length()<allFiles[i].length()) {
					File file = allFiles[j];
					allFiles[j] = allFiles[i];
					allFiles[i] = file;
				}
			}
		}
	}

	@Override
	public void printFiles() {
		for(int i = 0; i < allFiles.length; i++) {
			long fileSize = allFiles[i].length();
			String name = allFiles[i].getName();
			System.out.println((i+1)+" : "+name+"("+fileSize+"字节)");
		}
	}
	
}

测试程序

Example1Test.java

public class Example1Test {
	@Test
	public void testMain() {
		File dir = new File("D:/work_and_study");
		AbstractTemplate template = new ConcreteTemplate1(dir);
		System.out.println(dir.getPath()+"目录下的文件:");
		template.showFileName();
		template = new ConcreteTemplate2(dir);
		System.out.println(dir.getPath()+"目录下的文件:");
		template.showFileName();
		
	}
}

四、模板方法模式的优点。

  1. 可以通过在抽象模板定义模板方法给出成熟的算法步骤,同时又不限制步骤的细节,具体模板实现算法细节不会改变整个算法骨架。
  2. 在抽象模板模式中,可以通过钩子方法对某些步骤进行挂钩,具体模板通过钩子可以选择算法骨架中的某些步骤。

五、适合模板方法模式的情景。

  1. 设计者需要给出一个算法的固定步骤,并将某些步骤的具体实现留给子类来实现。
  2. 需要对代码进行重构,将各个子类公共行为提取出来集中到一个共同的父类中以避免代码重复。