理解
涵义:定义了一个算法的步骤,允许子类实现其中的一个或多个步骤
- 模版方法普遍是在多个类中有些算法步骤一成不变的出现,或是类与类算法步骤是相同,但具体实现有差异,可以将相同的部分提取出来封装起来,定义基本算法骨架,然后让子类去继承实现
- 模版方法在实际中应用很多,其重要性不在于提供的步骤,而是把相同代码提取出来进行封装的思想
应用环境
只要多个类都要按一定算法步骤去写,就能提取封装
- 典型是jdbc每次数据库都要连接,操作,关闭连接,可以将步骤封装,后面已举例
- 在spring代理模式中,HibernateTemplate就是对事务开启和关闭的封装,十分方便
用到的设计原则
好莱坞原则----别调用我们,我们会调用你
意思就是,当设计之中有高层组件和底层组件的时候,尽量让二者不要互相依赖,实现最大程度解耦,而设计的依赖,则应是高层依赖底层。简单说就是抽象的依赖(调用)具体的,因此我们设计中,也会说依赖抽象不依赖具体,当我们依赖抽象的时候,让抽象去依赖具体,则我们写程序时就实现了一定的解耦,也避免了吧代码写死。
优点
-
- 把算法骨架封装起来,实现了代码的复用,有效减少工作量
- 对于封装的灵活的话,对以后的维护扩展有很大帮助
缺点
- 引入抽象类,导致类关系变复杂(小毛病)
- 如果模版步骤行为切分过细,后期实现就不一定会符合了,因此适当预留钩子函数是不错的选择(即没有实现任何功能的函数,可在子类中按需实现)
主要组成
抽象模版类 | 定义算法步骤的抽象类,有些函数等着子类实现 |
子类 | 实现算法中没有完成的部分 |
类图
下面是我程序的类图
java源程序
因为我们使用jdbc做简单程序的时候,要求先取得连接,再操作数据库,而后关闭连接,既然步骤固定,那我就对获取连接进行封装。实例如下
抽象连接模版
package template_04;
import java.sql.DriverManager;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
public abstract class JdbcAbstract {
Connection conn = null;
public void connTemplate(){//把算法步骤封装起来
this.getConnect();
this.operate();
this.closeConnect();
}
public final void getConnect() {
try {
String url = "jdbc:mysql://localhost:3306/spring";
String pwd = "root";
String name = "root";
Class.forName("com.mysql.jdbc.Driver");
conn = (Connection) DriverManager.getConnection(url, name, pwd);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public abstract void operate();//有些功能去让子类实现
public final void closeConnect() {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
查询数据库操作
package template_04;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Statement;
public class QueryUser extends JdbcAbstract{
public void operate() {
try {
Statement st=(Statement) conn.createStatement();
ResultSet rs=st.executeQuery("select * from user");
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("name"));
}
rs.close();
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
插入数据库操作
package template_04;
import java.sql.SQLException;
import com.mysql.jdbc.PreparedStatement;
public class InsertUser extends JdbcAbstract{
public void operate() {
try {
String str="insert into user values(null,?);";
PreparedStatement ps=(PreparedStatement) conn.prepareStatement(str);
ps.setString(1, "template");
ps.execute();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
客户端
package template_04;
public class Client {
public static void main(String[] args) {
QueryUser qu=new QueryUser();
qu.connTemplate();
InsertUser iu=new InsertUser();
iu.connTemplate();
}
}
查询结果
数据库的表(插入结果)