14. Template Method 本質:固定算法骨架
14.1 實現應用系統的前臺和後臺的登錄控制
public class LoginModel {
private String loginId;
private String password;
public String getLoginId() {
return loginId;
}
public void setLoginId(String loginId) {
this.loginId = loginId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
public abstract class LoginTemplate {
public final boolean login(LoginModel lm) {
LoginModel lmFromDb = this.findLoginUser(lm.getLoginId());
if (lmFromDb != null) {
String encryptPwd = this.encryptPwd(lm.getPassword());
lm.setPassword(encryptPwd);
return this.match(lm, lmFromDb);
}
return false;
}
public boolean match(LoginModel lm, LoginModel lmFromDb) {
if (lm.getLoginId().equals(lmFromDb.getLoginId()) && lm.getPassword().equals(lmFromDb.getPassword())) {
return true;
}
return false;
}
public String encryptPwd(String password) {
return password;
}
public abstract LoginModel findLoginUser(String loginId);
}
public class NormalLogin extends LoginTemplate{
@Override
public LoginModel findLoginUser(String loginId) {
LoginModel lm = new LoginModel();
lm.setLoginId(loginId);
lm.setPassword("normal");
return lm;
}
}
public class WorkerLogin extends LoginTemplate{
@Override
public LoginModel findLoginUser(String loginId) {
LoginModel lm = new LoginModel();
lm.setLoginId(loginId);
lm.setPassword("worker");
return lm;
}
public String encryptPwd(String pwd) {
System.out.println("Encrypt using MD5");
return pwd;
}
}
public class TemplateClient {
public static void main(String[] args) {
LoginModel lm = new LoginModel();
lm.setLoginId("admin");
lm.setPassword("worker");
LoginTemplate lt = new WorkerLogin();
LoginTemplate lt2 = new NormalLogin();
System.out.println("Login portal: " + lt2.login(lm));
System.out.println("Login console: " + lt.login(lm));
}
}
/**
* 封裝進行登錄控制所需要的數據,在公共數據的基礎上,
* 添加具體模塊需要的數據
*/
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;
}
}
/**
* 普通用戶登錄控制加強版的邏輯處理
*/
public class NormalLogin2 extends LoginTemplate{
@Override
public LoginModel findLoginUser(String loginId) {
NormalLoginModel nlm = new NormalLoginModel();
nlm.setLoginId(loginId);
nlm.setPassword("normal");
nlm.setQuestion("question");
nlm.setAnswer("answer");
return nlm;
}
public boolean match(LoginModel lm, LoginModel lmFromDb) {
//這個方法需要覆蓋,因爲現在進行登錄控制的時候,
//需要檢測4個值是否正確,而不僅僅是缺省的2個
//先調用父類實現好的,檢測編號和密碼是否正確
boolean isSuperMatch = super.match(lm, lmFromDb);
if (isSuperMatch) {
//如果編號和密碼正確,繼續檢查問題和答案是否正確
//先把數據轉換成自己需要的數據
NormalLoginModel nlm = (NormalLoginModel)lm;
NormalLoginModel nlmFromDb = (NormalLoginModel)lmFromDb;
//檢查問題和答案是否正確
if (nlm.getQuestion().equals(nlmFromDb.getQuestion()) && nlm.getAnswer().equals(nlmFromDb.getAnswer())) {
return true;
}
}
return false;
}
}
public class TemplateClient2 {
public static void main(String[] args) {
NormalLoginModel nlm = new NormalLoginModel();
nlm.setLoginId("user");
nlm.setPassword("normal");
nlm.setQuestion("question");
nlm.setAnswer("answer");
LoginTemplate lt3 = new NormalLogin2();
System.out.println("Login portal 2: " + lt3.login(nlm));
}
}
14.2 重構時把相同的代碼抽取到父類中, 然後通過鉤子函數約束其行爲。
public abstract class HummerModel {
/*
* 首先,這個模型要能夠被髮動起來,別管是手搖發動,還是電力發動,反正
* 是要能夠發動起來,那這個實現要在實現類裏了
*/
protected abstract void start();
//能發動,那還要能停下來,那纔是真本事
protected abstract void stop();
//喇叭會出聲音,是滴滴叫,還是嗶嗶叫
protected abstract void alarm();
//引擎會轟隆隆的響,不響那是假的
protected abstract void engineBoom();
//那模型應該會跑吧,別管是人退的,還是電力驅動,總之要會跑
final public void run() {
//先發動汽車
this.start();
//引擎開始轟鳴
this.engineBoom();
//通過鉤子方法約束行爲:要讓它叫的就是就叫,喇嘛不想讓它響就不響
if(this.isAlarm()){
this.alarm();
}
//到達目的地就停車
this.stop();
}
//鉤子方法,默認喇叭是會響的
protected boolean isAlarm(){
return true;
}
}
public class HummerH1Model extends HummerModel {
private boolean alarmFlag = true; //是否要響喇叭
@Override
protected void alarm() {
System.out.println("悍馬H1鳴笛...");
}
@Override
protected void engineBoom() {
System.out.println("悍馬H1引擎聲音是這樣在...");
}
@Override
protected void start() {
System.out.println("悍馬H1發動...");
}
@Override
protected void stop() {
System.out.println("悍馬H1停車...");
}
protected boolean isAlarm() {
return this.alarmFlag;
}
//要不要響喇叭,是有客戶的來決定的
public void setAlarm(boolean isAlarm){
this.alarmFlag = isAlarm;
}
}
public class HummerH2Model extends HummerModel {
protected void alarm() {
System.out.println("悍馬H2鳴笛...");
}
protected void engineBoom() {
System.out.println("悍馬H2引擎聲音是這樣在...");
}
protected void start() {
System.out.println("悍馬H2發動...");
}
protected void stop() {
System.out.println("悍馬H2停車...");
}
//默認沒有喇叭的
protected boolean isAlarm() {
return false;
}
}
public class Client {
public static void main(String[] args) throws IOException {
System.out.println("-------H1型號悍馬--------");
System.out.println("H1型號的悍馬是否需要喇叭聲響?0-不需要 1-需要");
String type=(new BufferedReader(new InputStreamReader(System.in))).readLine();
HummerH1Model h1 = new HummerH1Model();
if(type.equals("0")){
h1.setAlarm(false);
}
h1.run();
System.out.println("\n-------H2型號悍馬--------");
HummerH2Model h2 = new HummerH2Model();
h2.run();
}
}
14. Template Method模式代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.