目录
模板方法模式
本质:固定算法骨架
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。
用抽象类存放相同逻辑,再声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类实现不同抽象方法,也就是不同的剩余逻辑。
UML图
- 抽象模版(AbstractClass):
- 一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。
- 具体模版(ConcreteClass):
- 实现父类的一个或多个抽象方法。
应用场景
一系列步骤相同,但个别步骤在更详细的层次上的实现可能不同的时候
优缺点
优点:实现代码复用
缺点:模板和子类的耦合性高,如要对模板中的算法骨架进行变更,会影响子类变化
实例:连接数据库实现登录
1.问题:假设要做一个登录系统,每个角色(普通用户、管理员、超级管理员)的登录功能相似但又有所差别,那么我们会如何设计这个系统呢?
2.思路:设计一个抽象的模板方法,它实现每个具体类重复的代码(比如从数据库中查询用户名和密码),每个具体类中再实现各自不同的功能(比如不同角色密码的加密方式不同)
3.UML图:
4.代码:
package com.login;
import java.sql.*;
public abstract class DBMS {
protected Connection conn=null;
protected PreparedStatement ps=null;
protected ResultSet rs=null;
boolean ok=false;//默认登录失败
public Connection getConn() {
return conn;
}
public PreparedStatement getPs() {
return ps;
}
public ResultSet getRs() {
return rs;
}
public abstract void Process(String name, String psw);
public boolean login(String name,String psw) {
try {
String Driver="com.mysql.cj.jdbc.Driver";
String url="xxxx";
String user="xxx";
String password="xxx";
Class.forName(Driver);
conn=DriverManager.getConnection(url,user,password);
Process(name,psw);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(ps!=null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return ok;
}
}
package com.login;
import java.sql.*;
public class Customer extends DBMS{
//普通用户
@Override
public void Process(String name,String psw) {
// TODO Auto-generated method stub
try {
String sql="select * from admin where username='"+name+"'and password='"+psw+"' ";
Connection conn=getConn();
ps=conn.prepareStatement(sql);
rs=ps.executeQuery();
if(rs.next()) {
ok=true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.login;
import java.sql.Connection;
import java.sql.SQLException;
public class Registrat extends DBMS{
//管理员账户
@Override
public void Process(String name,String psw) {
try {
String newname=Code(name);
String newpsw=Code(psw);
String sql="select * from admin where username='"+newname+"'and password='"+newpsw+"' ";
Connection conn=getConn();
ps=conn.prepareStatement(sql);
rs=ps.executeQuery();
if(rs.next()) {
ok=true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.login;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
//让用户输入用户名和密码
String name=cin.next();
String password=cin.next();
//连接数据库,验证用户名和密码是否正确
Customer c=new Customer();
boolean ok= (boolean) c.login(name,password);
System.out.println(ok?"登陆成功":"登录失败");
cin.close();
}
}