상세 컨텐츠

본문 제목

[3.3] JDBC 전략 패턴의 최적화

토비의스프링

by kwanghyup 2020. 10. 28. 23:56

본문

#전략 클래스의 추가 정보

 

add()메소드에도 전략 패턴을 적용해보자.

 

AddStatement 클래스 

package springbook.user.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import springbook.user.domain.User;

public class AddStatement implements StatementStrategy{

	User user;
	
    // 생성자로부터 user정보를 받는다.
	public AddStatement(User user) {
		this.user = user;
	}
	
	@Override
	public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
		String sql = "insert into users values(?,?,?)";
		PreparedStatement ps = c.prepareStatement(sql);
		ps.setString(1,user.getId());
		ps.setString(2,user.getName());
		ps.setString(3,user.getPassword());
		return ps;
	}

}

 

UserDao의 add()메소드

public void add(User user) throws ClassNotFoundException, SQLException {
	StatementStrategy st = new AddStatement(user);
	jdbcContextWithStatementStrategy(st);
}

테스트를 수행하면 성공한다.

 

# 전략 클라이언트와 동거

 

지금까지의 방식은 DAO메소드마다 

새로운 StatementStrategy 구현클래스를 만들어야한다.

 

이렇게 되면 기존 UserDao때보다

클래스 파일의 개수가 많이 늘어난다

 

로컬클래스의 이용 

 

전략클래스를 매번 독립된 파일로 만들지 말고

UserDao클래스 안에 내부에 클래스로 정의한다.

	public void add(final User user) throws ClassNotFoundException, SQLException {
		
		class AddStatement implements StatementStrategy{ // 내부에 선언된 로컬클래스 
			@Override
			public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
				String sql = "insert into users values(?,?,?)";
				PreparedStatement ps = c.prepareStatement(sql);
				ps.setString(1,user.getId());
				ps.setString(2,user.getName());
				ps.setString(3,user.getPassword());
				return ps;
			}
		}
		
		StatementStrategy st = new AddStatement();
		jdbcContextWithStatementStrategy(st);
		
	}

 

 

로컬클래스는 자신이 선언된 add()메소드의 로컬변수에 접근할 수 있다.

파라미터도 일종의 로컬변수이므로 AddStatment클래스에서

add()메소드의 파라미터인 user 변수에 접근이 가능하다.

 

따라서 user정보를 전달받기 위해 만들었던

생성자와 인스턴스 변수를 제거해도된다.

 

다만 내부 클래스에서 외부의 변수를 사용할 때는

외부변수는 반드시 final로 선언해줘야 한다.

 

익명 내부 클래스

 

AddStatement클래스는 add()메소드에서만 사용할 용도로 만들어졌다.

그렇다면 이름을 제거해도 무방하다.

 

public void add(final User user) throws ClassNotFoundException, SQLException {
	StatementStrategy st = new StatementStrategy() {
		@Override
		public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
			String sql = "insert into users values(?,?,?)";
			PreparedStatement ps = c.prepareStatement(sql);
			ps.setString(1,user.getId());
			ps.setString(2,user.getName());
			ps.setString(3,user.getPassword());
			return ps;
		}
	};
	jdbcContextWithStatementStrategy(st);
}

 

deleteAll()메소드도 같은 방식으로 고쳐보자.

public void deleteAll() throws SQLException {
	StatementStrategy st = new StatementStrategy() {
		
		@Override
		public PreparedStatement makePreparedStatement(Connection c) throws SQLException {
			return c.prepareStatement("truncate users");
		}
	};
	jdbcContextWithStatementStrategy(st);
}

 

 

 

 

 

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

[3.5] 템플릿과 콜백  (0) 2020.10.29
[3.4] 컨텍스트와 DI  (0) 2020.10.29
[3.2] 변하는 것과 변하지 않는 것  (0) 2020.10.28
[3.1] 다시 보는 초난감DAO  (0) 2020.10.28
[2.4] 스프링 테스트 적용  (0) 2020.10.28

관련글 더보기

댓글 영역