模板方法模式的本质:
固定算法骨架
package com;
public class LoginModel {
private String loginId;
private String pwd;
public String getLoginId() {
return loginId;
}
public void setLoginId(String loginId) {
this.loginId = loginId;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
package com;
/*
* 模板操作类
*/
public abstract class LoginTemplate {
public boolean login(LoginModel inputUser){
LoginModel dbuser = findLoginUser(inputUser.getLoginId());
inputUser.setPwd(encryptPwd(inputUser.getPwd()));
return match(inputUser,dbuser);
}
protected abstract LoginModel findLoginUser(String loginId);
protected String encryptPwd(String pwd){
return pwd;
}
protected boolean match(LoginModel inputUser,LoginModel dbuser){
return inputUser.getPwd().equals(dbuser.getPwd());
}
}
package com.impl;
import com.LoginModel;
import com.LoginTemplate;
public class NormalLogin extends LoginTemplate {
@Override
protected LoginModel findLoginUser(String loginId) {
//这里省略具体的处理,仅做示意,返回一个有默认数据的对象,可能访问的是不用的表
LoginModel dbUser = new LoginModel();
dbUser.setLoginId(loginId);
dbUser.setPwd("12345");
return dbUser;
}
}
package com.impl;
import com.LoginModel;
import com.LoginTemplate;
public class WorkerLogin extends LoginTemplate {
@Override
protected LoginModel findLoginUser(String loginId) {
//这里省略具体的处理,仅做示意,返回一个有默认数据的对象,可能访问的是不用的表
LoginModel dbUser = new LoginModel();
dbUser.setLoginId(loginId);
dbUser.setLoginId("56789");
return dbUser;
}
@Override
protected String encryptPwd(String pwd){
System.out.println("使用MD5进行密码加密");
return pwd;
}
}
import com.LoginModel;
import com.LoginTemplate;
import com.impl.NormalLogin;
import com.impl.WorkerLogin;
public class Client {
public static void main(String[] args) {
LoginModel inputUser = new LoginModel();
inputUser.setLoginId("SHIXIN");
inputUser.setPwd("12345");
LoginTemplate normalLogin = new NormalLogin();
System.out.println(normalLogin.login(inputUser));
LoginTemplate workerLogin = new WorkerLogin();
System.out.println(workerLogin.login(inputUser));
}
}
功能扩展分析:
1.只需要提供新的子类实现就可以了。比如想要切换不同的加密算法,现在使用MD5,新的子类覆盖Template类的encryptPwd方法。
2.给两个登陆模块都扩展同一个功能,这种情况多属于需要修改模板方法的算法的骨架的情况,应该尽量避免,但是万一前面没有考虑周全,后来出现了这种情况,怎么办呢?最好就是重构,也就是考虑修改算法框架,尽量不要考虑其他的替代方式,替代的方式也许能把功能实现了,但是会破坏整个程序的结构。
3.既需要加入新的功能,也需要新的数据。由于需要一些其他的数据,那么就需要扩展LoginModel,加入自己需要的数据;同时可能需要覆盖父类提供的一些公共的方法,来实现新的功能。
package com;
public class NormalLoginModel extends LoginModel{
private String question;
private String answer;
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
}
package com.impl;
import com.LoginModel;
import com.LoginTemplate;
import com.NormalLoginModel;
public class NormalLogin2 extends LoginTemplate {
@Override
protected LoginModel findLoginUser(String loginId) {
//这里省略具体的处理,仅做示意,返回一个有默认数据的对象,可能访问的是不用的表
NormalLoginModel dbUser = new NormalLoginModel();
dbUser.setLoginId(loginId);
dbUser.setPwd("12345");
dbUser.setQuestion("testQuestion");
dbUser.setAnswer("testAnswer");
return dbUser;
}
@Override
protected boolean match(LoginModel inputUser, LoginModel dbuser) {
boolean b = super.match(inputUser, dbuser);
if(b){
NormalLoginModel NormalInputUser = (NormalLoginModel) inputUser;
NormalLoginModel NormalDbuser = (NormalLoginModel) dbuser;
b = NormalInputUser.getQuestion().equals(NormalDbuser.getQuestion())
&& NormalInputUser.getAnswer().equals(NormalDbuser.getAnswer());
}
return b;
}
}
import com.LoginTemplate;
import com.NormalLoginModel;
import com.impl.NormalLogin2;
public class Client {
public static void main(String[] args) {
NormalLoginModel inputUser = new NormalLoginModel();
inputUser.setLoginId("SHIXIN");
inputUser.setPwd("12345");
inputUser.setQuestion("testQuestion");
inputUser.setAnswer("testAnswer");
LoginTemplate normalLogin2 = new NormalLogin2();
System.out.println(normalLogin2.login(inputUser));
}
}