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();            }        }