模板方法模式(Template Method)
@@@模式定义:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
@@@练习示例:
登录控制
@@@示例代码:
\src\pattern\LoginModel.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 封装进行登录控制所需要的数据 */ 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; } }
\src\pattern\LoginTemplate.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 登录控制的模板 */ public abstract class LoginTemplate { /** * 判断登录数据是否正确,也就是是否能登录成功 * @param lm 封装登录数据的Model * @return true表示登录成功,false表示登录失败 */ public final boolean login(LoginModel lm) { // 1:根据登录人员的编号去获取相应的数据 LoginModel dbLm = this.findLoginUser(lm.getLoginId()); if (dbLm != null) { // 2:对密码进行加密 String encryptPwd = this.encryptPwd(lm.getPwd()); // 把加密后的密码设置回到登录数据模型中 lm.setPwd(encryptPwd); // 3:判断是否匹配 return this.match(lm, dbLm); } return false; } /** * 根据登录编号来查找和获取存储中相应的数据 * @param loginId 登录编号 * @return 登录编号在存储中相对应的数据 */ public abstract LoginModel findLoginUser(String loginId); /** * 对密码数据进行加密 * @param pwd 密码数据 * @return 加密后的密码数据 */ public String encryptPwd(String pwd) { return pwd; } /** * 判断用户填写的登录数据和存储中对应的数据是否匹配得上 * @param lm 用户填写的登录数据 * @param dbLm 在存储中对应的数据 * @return true表示匹配成功,false表示匹配失败 */ public boolean match(LoginModel lm, LoginModel dbLm) { if (lm.getLoginId().equals(dbLm.getLoginId()) && lm.getPwd().equals(dbLm.getPwd())) { return true; } return false; } }
\src\pattern\NormalLogin.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 普通用户登录控制的逻辑处理 */ public class NormalLogin extends LoginTemplate { @Override public LoginModel findLoginUser(String loginId) { // 这里省略具体的处理,仅做示意,返回一个有默认数据的对象 LoginModel lm = new LoginModel(); lm.setLoginId(loginId); lm.setPwd("userPwd"); return lm; } }
\src\pattern\WorkerLogin.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package pattern; /** * 工作人员登录控制的逻辑处理 */ public class WorkerLogin extends LoginTemplate { @Override public LoginModel findLoginUser(String loginId) { // 这里省略具体的处理,仅做示意,返回一个有默认数据的对象 LoginModel lm = new LoginModel(); lm.setLoginId(loginId); lm.setPwd("workerPwd"); return lm; } @Override public String encryptPwd(String pwd) { // 覆盖父类的方法,提供真正的加密实现 // 这里对密码进行加密,比如使用MD5、3DES等,省略了 System.out.println("使用MD5进行密码加密"); return pwd; } }
\src\user\Client.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package user; import pattern.LoginModel; import pattern.LoginTemplate; import pattern.NormalLogin; import pattern.WorkerLogin; public class Client { public static void main(String[] args) { // 准备登录人的信息 LoginModel lm = new LoginModel(); lm.setLoginId("admin"); lm.setPwd("workerPwd"); // 准备用来进行判断的对象 LoginTemplate lt1 = new WorkerLogin(); LoginTemplate lt2 = new NormalLogin(); // 进行登录测试 boolean flag1 = lt1.login(lm); System.out.println("可以登录工作平台=" + flag1); boolean flag2 = lt2.login(lm); System.out.println("可以进行普通人员登录=" + flag2); } }
@@@模式的实现:
1) 一般实现成抽象类(“既要约束子类的行为, 又要为子类提供公共功能”);
2) 理论依据是“后期绑定”技术(new谁就调用谁的方法);
3) 可以使用继承方式还可以使用回调方式
@@@模式的优点:
1) 实现代码复用;
@@@模式的缺点:
1) 算法骨架不容易升级;
@@@模式的本质:
固定算法骨架。
@@@模式体现的设计原则:
1) 开闭原则;
2) 里氏替换原则;