본문 바로가기
책 정리/토비의 스프링

3. 템플릿

by 이석준석이 2021. 1. 23.

0. 템플릿이란

  • 변경이 거의 일어나지 않으며 일정한 패턴으로 유지되는 특성을 가진 부분을 독립시켜서 효과적으로 사용하는 방법

1. 예외처리 기능을 갖춘 DAO

  • 현재까지 구현한 DAO에서는 Connection과 PrepareStatement 를 통해 데이터베이스에서 데이터를 가져온다.

리소스 반환이 필수적이다.

  • pool 방식으로 운영된다.
    • 미리 정해진 풀에 제한된 수의 Connection을 만들어 필요한 경우 사용한다.
    • 예외가 발생할 시, Connection close() 를 해줘야 한다.

2. 리팩토링

 

1. 템플릿메소드를 통한 리팩토링

  • 자주 변하는 부분 (preparestatement 부분) 에 대해서 상속관계를 통해서 분리한다.
  • 상위클래스의 변경에 민감하게 된다. 유연성 zero


2. 전략 패턴을 통한 리팩토링

  • 변하지 않는 부분 : Context
  • 변하는 부분 : Strategy

코드내에서의 문제

  • 코드내에서 new DeleteAllStatement() 가 보이게된다.
  • 위의 그림에서 Strategy에만 의존성이 있는게 아닌, 구현체자체에 의존성이 생기므로 OCP를 위반
public void deleteAll() throws SQLException {
    ...
    try {
        c = dataSource.getConnection();
        
        Strategy strategy = new DeleteAllStatement();
        ps = strategy.makePrepareStatement(c);

        ps.executeUpdate();
    } catch (SQLException e) {
    ...
}

 

1장에서 했던 것 처럼, 생성을 담당하는 클라이언트가 필요하다.

  • 파라미터로 받도록하여 구현체에 의존성을 제거하자!
public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException {
    Connection c = null;
    PreparedStatement ps = null;

    try {
        c = dataSource.getConnection();

        ps = stmt.makePrepareStatement(c);

        ps.executeUpdate();
    } catch (SQLException e) {
    ...
}

3. 전략패턴의 구현체 클래스가 계속 많아지는 문제를 해결

 

1. 로컬클래스

  • 구현체를 클래스 내부에서 내부클래스로 사용하여 정의

2. 익명 내부 클래스

  • 바로 new로해서 interface를 구현하여 사용

4. 템플릿 콜백

 

현재 add() 메소드의 상태

  • UserDao 가 JdbcContext (템플릿) 를 호출한다.
  • JdbcContext 내부에서 makePrepareStatement() (콜백 메소드) 호출
  • makePrepareStatement() 는 익명클래스로서 UserDao 내부에 있기 때문에 콜백으로 호출
  • JdbcContext는 결과를 받아 UserDao에 반환
public class UserDao {

    ...

    public void add(final User user) throws SQLException {
        jdbcContext.workWithStatementStrategy(c -> {
            PreparedStatement ps = c.prepareStatement(
                    "insert into users(id, name, password) values (?, ?, ?)");

            ps.setString(1, user.getId());
            ps.setString(2, user.getName());
            ps.setString(3, user.getPassword());
            return ps;
        });
    }
}

// Context(template)
public class JdbcContext {
 	...
    public void workWithStatementStrategy(StatementStrategy stmt) throws SQLException {
		...
        try {
            c = dataSource.getConnection();

            ps = stmt.makePrepareStatement(c);

            ps.executeUpdate();
        } catch (SQLException e) {
        ...
    }
}

 

연습을 위한 예제는 토비의스프링 248page calculator 만드는 부분을 참조!

'책 정리 > 토비의 스프링' 카테고리의 다른 글

6.1. AOP  (0) 2021.02.02
5. 서비스 추상화  (0) 2021.02.01
4. 예외  (0) 2021.01.30
2. 테스트  (0) 2021.01.23
1장 오브젝트와 의존관계  (0) 2021.01.19