行为模式——模板方法模式
一、定义
模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。
二、问题
假设现在你要做一个登录系统,每个角色(普通用户、管理员、超级管理员)的登录功能相似但又有所差别,那么我们会如何设计这个系统呢?
三、解决方案
我们可以设计一个抽象的模板方法,它实现一些每个具体类重复的代码(比如从数据库中查询用户名和密码),每个具体类中再实现各自不同的功能(比如 不同角色密码的加密方式不同)
四、代码实现
1、抽象类 (AbstractClass) 会声明作为算法步骤的方法, 以及依次调用它们的实际模板方法。 算法步骤可以被声明为 抽象类型, 也可以提供一些默认实现。
package com.atmae.templateMethod;
import java.util.Objects;
/**
* @Author: Mae
* @Date: 2022/4/14
* @Time: 8:08
* @Description:
*/
public abstract class Login {
protected String username;
protected String password;
/**
* 登录接口
*
* @return true/false
*/
public abstract boolean login(String username, String password);
/**
* 从数据库中根据用户名查询密码判断是否匹配 (模拟)
* @param username 用户名
* @param password 密码
*/
public boolean getPasswordByDatabase(String username, String password) {
//数据库中先查询有无此用户名
String sql = "select username,password from sys_user where username=?";
//模拟执行sql语句
//映射成user对象
User user = excute(sql,username);
if (Objects.isNull(user)) {
return false;
} else {
return user.passowrd.equals(password);
}
}
}
2、
管理员
package com.atmae.templateMethod;
/**
* @Author: Mae
* @Date: 2022/4/14
* @Time: 8:08
* @Description: 管理员
*/
public class AdminLogin extends Login {
@Override
public boolean login(String username, String password) {
//根据用户名去数据库中查询密码是否匹配
//判断是否可以登录
//普通管理员密码进行JWT加密
String newPassword=parseJWT(password);
return getPasswordByDatabase(username,newPassword);
}
public String parseJWT(String password){
return JWT.parse(password);
}
}
超级管理员
package com.atmae.templateMethod;
import java.util.Objects;
/**
* @Author: Mae
* @Date: 2022/4/14
* @Time: 8:10
* @Description: 超级管理员
*/
public class SuperAdminLogin extends Login{
@Override
public boolean login(String username, String password) {
//超级管理员的密码使用对称加密算法加密(模拟)
String newPassword=parseDES(password);
return getPasswordByDatabase(username,newPassword);
}
public String parseDES(String password){
return DES.parse(password);
}
}
普通用户
package com.atmae.templateMethod;
import sun.security.provider.MD5;
import java.util.Objects;
/**
* @Author: Mae
* @Date: 2022/4/14
* @Time: 8:11
* @Description:
*/
public class UserLogin extends Login {
@Override
public boolean login(String username, String password) {
//根据用户名去数据库中查询密码是否匹配
//判断是否可以登录
//普通用户密码MD5盐值 加密(模拟)
String newPassword= parseMD5(password);
return getPasswordByDatabase(username,newPassword);
}
public String parseMD5(String password){
return MD5.parse(password);
}
}
3、客户端
package com.atmae.templateMethod;
/**
* @Author: Mae
* @Date: 2022/4/14
* @Time: 9:01
* @Description:
*/
public class Client {
public static void main(String[] args) {
//超级管理员登录
Login user=new SuperAdminLogin();
user.login("1122","454545");
}
}
五、UML图
六、模板方法模式使用场景
- 只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。
- 当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生变化, 你就可能需要修改所有的类。
七、总结
优点
- 允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。
- 可将重复代码提取到一个超类中
缺点
- 模板方法中的步骤越多, 其维护工作就可能会越困难。
- 违反里氏替换原则,(父类拥有的性质 子类不一定成立了)
八、与其他模式的关系
- 工厂方法模式是模板方法模式的一种特殊形式。 同时, 工厂方法可以作为一个大型模板方法中的一个步骤。
- 模板方法基于继承机制: 它允许你通过扩展子类中的部分内容来改变部分算法。
策略模式基于组合机制: 你可以通过对相应行为提供不同的策略来改变对象的部分行为。
模板方法在类层次上运作, 因此它是静态的。
策略在对象层次上运作, 因此允许在运行时切换行为。