模板方法模式
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
这个模式是用来创建一个算法的模板。
模板就是一个方法,具体的说,这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这可以确保算法的结构保持不变,同时由子类提供部分实现。
例子:
系统登录(普通账号,管理员账号)
打开系统
填写信息(管理员账号需要多填一个动态密码)
提交登陆
行为日志记录(管理员账号需要记录行为日志)
我们把这组步骤做成一个模板。
package com.ez.biz;
import com.ez.Account;
import com.ez.impl.AdministratorAccount;
import com.ez.impl.CommonAccount;
/**
* 调用模板方法,就可以实现各自的登录。
* @author 窗外赏雪(EZ编程网)
*
*/
public class Test {
public static void main(String[] args) {
Account account=new AdministratorAccount();
account.loginIn();
System.out.println("==================");
account=new CommonAccount();
account.loginIn();
}
}
package com.ez;
/**
* 抽象类中定义模板方法和确定的方法。
* 账号类型不同,填写登录信息的方式也不同,所以fillInfo方法必须定义为抽象,交给子类去操心。
* @author 窗外赏雪(EZ编程网)
*/
public abstract class Account {
/**
* 这个方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。
* 这可以确保算法的结构保持不变,同时由子类提供部分实现。
* 模板方法声明为final,这样一来子类就无法覆盖它。
*/
public final void loginIn() {
openSystem();
fillInfo();
submit();
if (needFollow()) {
following();
}
}
/**
* 填写信息,普通用户只要填用户名和密码就可以了,管理员还需要再填下动态密码。
*/
public abstract void fillInfo();
/**
* 我们称这种方法为钩子,子类可以视情况决定要不要覆盖它们。
*/
public boolean needFollow() {
return true;
}
public final void openSystem() {
System.out.println("打开系统");
}
public final void submit() {
System.out.println("提交登录");
}
public final void following() {
System.out.println("行为日志记录");
}
}
package com.ez.impl;
import com.ez.Account;
/**
* 普通账号,权限比较低,不做行为日志记录。
* 覆盖needFollow返回false。
* 普通账号特有的填写登录信息
* @author 窗外赏雪(EZ编程网)
*/
public class CommonAccount extends Account{
@Override
public void fillInfo() {
System.out.println("普通账户只要填写用户名和密码");
}
@Override
public boolean needFollow() {
return false;
}
}
package com.ez.impl;
import com.ez.Account;
/**
* 管理员账号,由于权限比较大,所以要记录行为日志。
* 管理员特有的填写登录信息
* @author 窗外赏雪(EZ编程网)
*/
public class AdministratorAccount extends Account{
@Override
public void fillInfo() {
System.out.println("管理员账号需要填写用户名、密码以及动态密码");
}
}
在外面的世界,必须学会找出周围的模式,我们也必须学会识别模式的变体。
用模板方法排序
Java数组类的设计者提供给我们一个方便的模板方法用来排序。
模板方法包含一组步骤,拷贝数组,循环比较数组,交换元素位置等。
拷贝交换等方法都一样,在数组类中就可以定义好。
compareTo()方法要我们自己实现,因为每种事物的比较方式都不一样。
比方说我们要对人进行排序,只需要实现compareTo方法即可,一般都是通过实现Compareble接口来完成。
package com.ez.biz;
import java.util.Arrays;
/**
* 要实现数组排序,只需要实现compareTo方法即可。
* 其他逻辑,都已经在模板方法实现。
* @author 窗外赏雪(EZ编程网)
*/
public class Test {
public static void main(String[] args) {
People[] peoples={new People("李四", 25),
new People("王五", 28),
new People("赵六", 21)};
System.out.println("========排序前=======");
dispaly(peoples);
//把Arrays的sort方法认为是模板方法
Arrays.sort(peoples);
System.out.println("========排序后=======");
dispaly(peoples);
}
public static void dispaly(People[] peoples){
for (People people:peoples) {
System.out.println(people);
}
}
}
package com.ez.biz;
/**
* 实现compareTo方法,实现模板方法中不确定的方法。
* @author 窗外赏雪(EZ编程网)
*/
public class People implements Comparable<People>{
private String name;
private int age;
public People(String name,int age) {
this.name=name;
this.age=age;
}
@Override
public int compareTo(People o) {
if(this.age<o.age){
return -1;
}else if(this.age==o.age){
return 0;
}else{
return 1;
}
}
@Override
public String toString() {
return "name: "+name+", age: "+age;
}
}