首页 > 代码库 > 设计模式入门之模板方法模式TemplateMethod

设计模式入门之模板方法模式TemplateMethod

模板方法模式定义:

定义一个算法的骨架,而将步骤延迟到子类中。这种模式可以使得在不改变算法骨架(模板)的情况下修改每个步骤的具体实现

从功能上来看,这个模式跟生成器模式有些相像,只不过生成器模式定义了创建对象的过程,而模板方法模式定义了算法过程

感觉这个模式要简单很多。

钩子:可以被子类覆盖以实现扩展的方法通常叫做钩子

实例:用户登录过程,分为后台人员登录和用户登录,这是一个非常成型的技术过程,是非常典型的模板方法模式的应用,其中普通用户密码不需要加密,而工作人员的密码需要进行加密比对。上代码

//登录Model
//封装进行登录控制所需要的数据
public class LoginModel {
	private String loginId;
	private String pwd;
	//get set methods
}
//定义登录控制的算法骨架
//因为登录中的过程是一致的,所以把过程抽象出来,用抽象类来定义子类公共方法
public abstract class LoginTemplate {
	public final boolean login(LoginModel lm) {
		LoginModel dbLm = this.findLoginUser(lm.getLoginId());
		if(dbLm != null) {
			String encryptPwd = this.encryptPwd(lm.getPwd());
			lm.setPwd(encryptPwd);
			return this.match(lm, dbLm);
		}
		return false;
	}

	public abstract LoginModel findLoginUser(String loginId);

	public String encryptPwd(String pwd) { //钩子
		return pwd;
	}

	public boolean match(LoginModel lm,LoginModel dbLm) {
		if(lm.getLoginId().equals(dbLm.getLoginId()) && lm.getPwd().equals(dbLm.getPwd())) {
			return true;
		}
		return false;
	}
}
//普通用户登录控制的逻辑处理
public class NormalLogin extends LoginTemplate {
	public LoginModel findLoginUser(String loginId) {
		LoginModel lm = new LoginModel();
		lm.setLoginId(loginId);
		lm.setPwd("password");
		return lm;
	}
}
//工作人员登录控制的逻辑处理
public class WorkerLogin extends LoginTemplate {
	public LoginModel findLoginUser(String loginId) {
		LoginModel lm = new LoginModel();
		lm.setLoginId(loginId);
		lm.setPwd("password");
		return lm;
	}

	public String encryptPwd(String pwd) {
		System.out.println("进行Md5加密");
		return pwd;
	}
}
//客户端调用
public class Client {
	public static void main(String[] args) {
		LoginModel lm = new LoginModel();
		lm.setLoginId("admin");
		lm.setPwd("workerpwd");

		LoginModel lm2 = new LoginModel();
		lm2.setLoginId("normaluser");
		lm2.setPwd("normalpwd");

		LoginTemplate lt = new WorkerLogin();
		LoginTemplate lt2 = new NormalLogin();

		boolean flag = lt.login(lm);
		System.out.println("可以登录工作平台="+flag);

		boolean flag2 = lt2.login(lm2);
		System.out.println("可以进行普通登录="+flag2);
	}
}
这里复习几个小的知识点:

1.接口和抽象类

(1)接口是特殊的抽象类,接口中所有方法必须是抽象的,不能有具体实现;而抽象类中可以有实现的方法

(2)抽象类不一定包含抽象方法,有抽象方法的类一定是抽象类

(3)需要约束子类行为时用接口,既要约束子类行为,又要为其提供公共功能时用抽象类

模板方法模式中提现了好莱坞法则:不要来找我们,我们会找你。因为在该例中,子类只定义了会被父类调用的方法,调用是从父类方法发起的