14. Template Method模式代码
来源:互联网 发布:约球软件 编辑:程序博客网 时间:2024/05/16 16:53
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(); } }