模板方法模式(Template Method Pattern)定义一个操作中的算法骨架,将某些步骤延迟到子类实现。
public abstract class AbstractTemplate {
// 模板方法(final防止子类覆盖)
public final void templateMethod() {
step1();
step2();
step3();
if(hook()) {
step4();
}
}
// 抽象方法(必须由子类实现)
protected abstract void step2();
// 具体方法(已有默认实现)
protected void step1() {
System.out.println("执行步骤1");
}
protected void step3() {
System.out.println("执行步骤3");
}
// 钩子方法(可选覆盖)
protected boolean hook() {
return true;
}
protected void step4() {
System.out.println("执行步骤4");
}
}
public class ConcreteClassA extends AbstractTemplate {
protected void step2() {
System.out.println("A实现-步骤2");
}
protected boolean hook() {
return false; // 关闭步骤4
}
}
public class ConcreteClassB extends AbstractTemplate {
protected void step2() {
System.out.println("B实现-步骤2");
}
protected void step4() {
System.out.println("B定制-步骤4");
}
}
public abstract class BeverageTemplate {
// 模板方法(final)
public final void prepareBeverage() {
boilWater();
brew();
pourInCup();
if(customerWantsCondiments()) {
addCondiments();
}
}
protected abstract void brew();
protected abstract void addCondiments();
protected void boilWater() {
System.out.println("煮沸水");
}
protected void pourInCup() {
System.out.println("倒入杯中");
}
// 钩子方法
protected boolean customerWantsCondiments() {
return true;
}
}
// 咖啡
public class Coffee extends BeverageTemplate {
protected void brew() {
System.out.println("冲泡咖啡粉");
}
protected void addCondiments() {
System.out.println("加糖和牛奶");
}
protected boolean customerWantsCondiments() {
String answer = getUserInput();
return answer.toLowerCase().startsWith("y");
}
private String getUserInput() {
System.out.print("要加糖和牛奶吗(y/n)? ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
return reader.readLine();
} catch (IOException e) {
return "no";
}
}
}
// 茶
public class Tea extends BeverageTemplate {
protected void brew() {
System.out.println("浸泡茶叶");
}
protected void addCondiments() {
System.out.println("加柠檬");
}
}
public class BeverageTest {
public static void main(String[] args) {
System.out.println("制作咖啡...");
BeverageTemplate coffee = new Coffee();
coffee.prepareBeverage();
System.out.println("\n制作茶...");
BeverageTemplate tea = new Tea();
tea.prepareBeverage();
}
}
public abstract class JdbcTemplate {
// 模板方法
public final T execute(String sql, RowMapper rowMapper) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = getConnection();
stmt = conn.prepareStatement(sql);
setParameters(stmt);
rs = stmt.executeQuery();
return rowMapper.mapRow(rs);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
closeResources(conn, stmt, rs);
}
}
protected abstract void setParameters(PreparedStatement stmt) throws SQLException;
protected Connection getConnection() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/test");
}
protected void closeResources(Connection conn, Statement stmt, ResultSet rs) {
try { if (rs != null) rs.close(); } catch (SQLException e) {}
try { if (stmt != null) stmt.close(); } catch (SQLException e) {}
try { if (conn != null) conn.close(); } catch (SQLException e) {}
}
}
public interface RowMapper {
T mapRow(ResultSet rs) throws SQLException;
}
public class UserDao extends JdbcTemplate {
public User findById(long id) {
return execute("SELECT * FROM users WHERE id = ?", rs -> {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
return user;
});
}
protected void setParameters(PreparedStatement stmt) throws SQLException {
stmt.setLong(1, 1L); // 设置查询参数
}
}
开闭原则
src/
├── main/
│ ├── java/
│ │ ├── template/
│ │ │ ├── AbstractTemplate.java
│ │ │ ├── ConcreteClassA.java
│ │ │ ├── ConcreteClassB.java
│ │ │ ├── BeverageTemplate.java
│ │ │ ├── Coffee.java
│ │ │ ├── Tea.java
│ │ │ ├── JdbcTemplate.java
│ │ │ ├── UserDao.java
│ │ │ └── BeverageTest.java