UserDao는 회원 User를 추가하고, 전체 목록을 삭제하는
add()
,deleteAll()
메서드를 가지고 있다. 그런데 빨간 박스를 제외하고 동일한 패턴이다.
중복된 코드를 제거하고 재사용성을 높이기 위해서 전략 패턴을 적용해보자.
jdbcContext()
에서 변하지 않는 부분을 동작하다가 변하는 부분은 Strategy 인터페이스를 통해 외부의 독립된 전략 클래스(AddStrategy
or DeleteAllStategy
)에 위임한다.
Add()
에서는 INSERT
쿼리문이 담긴 PreparedStatement
가 필요DeleteAll()
에서는 DELETE
쿼리문이 담긴 PreparedStatement
가 필요👉 따라서 PreparedStatement
를 반환해주는 인터페이스를 작성한다.
public interface StatementStrategy {
PreparedStatement makePreparedStatement(Connection conn) throws SQLException;
}
public class AddStrategy implements StatementStrategy {
private User user;
public AddStrategy(User user) {
this.user = user;
}
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
String sql = "INSERT INTO users(id, name, password) VALUES(?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getName());
pstmt.setString(3, user.getPassword());
return pstmt;
}
}
public class DeletAllStrategy implements StatementStrategy {
private String sql = "DELETE FROM users";
@Override
public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
return conn.prepareStatement(sql);
}
}
바뀌지않는 중복되는 흐름 그대로 가져간다.
바뀌는 부분에서는 파라미터로 전달받은 인터페이스의 메서드를 호출한다.
private void jdbcContext(StatementStrategy strategy) throws SQLException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = cm.getConnection();
pstmt = strategy.makePreparedStatement(conn); //전달받은 전략을 사용한다.
pstmt.executeUpdate();
} catch (SQLException e) {
throw e;
}
close(conn, pstmt, null);
}
public void add(User user) throws SQLException {
jdbcContextWithStatementStrategy(new AddStrategy(user));
}
public void deleteAll() throws SQLException {
jdbcContextWithStatementStrategy(new DeletAllStrategy());
}