김기헌
Strategy pattern을 적용하여 Refactoring
•
기존 코드
public class UserDao {
public void add(User user) {
Map<String, String> env = System.getenv();
try {
// DB접속 (ex sql workbeanch실행)
Connection c = connectionMaker.connectionMaker();
// Query문 작성
PreparedStatement pstmt = c.prepareStatement("INSERT INTO users(id, name, password) VALUES(?,?,?);");
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getName());
pstmt.setString(3, user.getPassword());
// Query문 실행
pstmt.executeUpdate();
pstmt.close();
c.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void deleteAll() throws SQLException {
Connection c = connectionMaker.connectionMaker();
PreparedStatement ps = c.prepareStatement("delete from users");
ps.executeUpdate();
ps.close();
c.close();
}
}
Java
복사
•
UserDao Strategy pattern 적용
public class UserDao {
private ConnectionMaker connectionMaker;
public void add(User user) { //add 적용
try {
jdbcContextWithStatementStrategy(new AddStrategy(user));
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public void deleteAll() throws SQLException { //delete 적용
jdbcContextWithStatementStrategy(new DeleteAllStragegy());
}
public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException{
Connection c = connectionMaker.connectionMaker();
PreparedStatement ps = stmt.makePreparedStatement(c);
ps.executeUpdate();
ps.close();
c.close();
}
}
Java
복사
•
interface
public interface StatementStrategy {
PreparedStatement makePreparedStatement(Connection connection)throws SQLException;
}
Java
복사
•
AddStrategy 구현체
public class AddStrategy implements StatementStrategy{
private User user;
public AddStrategy(User user){
this.user=user;
}
@Override
public PreparedStatement makePreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.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;
}
}
Java
복사
•
DeleteAllStrategy 구현체
public class DeleteAllStragegy implements StatementStrategy{
@Override
public PreparedStatement makePreparedStatement(Connection connection)throws SQLException{
return connection.prepareStatement("delete from users");
}
}
Java
복사
Strategy 패턴 적용 후 변경점
•
deleteAll, add 메소드의 삭제, 추가 행위를 DeleteAllStrategy class와 AddStategy makePreparedStatement 메소드에 넘겨줌으로써 deleteAll, add 메소드의 책임을 한 가지 줄였다
•
메소드마다 있던 공통로직 connection과 statement의 선언을 jdbcContextWithStatementStrategy 메소드로 분리하여 코드의 반복을 줄였다
김상호
이가현
알고리즘 괄호
메소드 만들때 먼저 생각해야 할 것
1.
반환타입을 어떤것으로 할지!
2.
매개변수로 어떤 값을 넣을지
stack 사용 안하고 괄호 문제 풀기
메소드 디자인
•
반환타입은 괄호가 남아있으면 false, 없으면 true
•
매개변수는 괄호는 문자이니깐 String 타입의 괄호를 입력받을 것
replace와 replaceAll
•
replace([기존문자], [바꿀문자])
•
replaceAll([정규식],[바꿀문자]
강사님이 만났던 문제
→ replaceAll의 첫번째 인자로는 정규식을 받기 때문에 정규식으로 작성해야 한다!
indexof
•
특정 문자나 문자열이 앞에서부터처음 발견되는 인덱스를 반환하며 만약 찾지 못했을 경우"-1"을 반환
Replace로 풀 경우 속도
O(N^2)
정규식이란? 
코드
stack으로 풀기
•
스택을 사용안하고도 할수 있는 방법은 있지만 출력하는데 시간이 너무 오래걸리기 때문에 stack으로 푸는게 가장 좋은 방법!
•
단, 처음 값이 ‘)’일 경우를 위해 예외처리를 필수 적으로 해야한다.
스택 쓰는 경우 연산 속도
O(N^2) –> O(N)
코드
test
스프링
복습하기
전날 복습
1.
deleteAll(), .getCount()추가 – 166p
2.
deleteAll(), .getCount() 테스트 추가
3.
@BeforeEach 적용하여 테스트코드 개선 – 182p
4.
findById()메소드에서 user == null인 경우 Exception처리 – 175p
5.
try / catch / finally 처리 – 213p
참고 . 강사님 유튜브 강의
JDBC try/catch/finally 코드의 문제점
•
토비의 스프링 p.216
•
Human 에러 가능성 : 리팩토링, 테스트를 하는 이유
•
추상화를 해서 리팩토링을 해야함.
분리와 재사용을 위한 디자인 패턴 적용
•
토비의 스프링 (p.222)
•
전략 패턴 (strategy 패턴) : interface를 의존(사용)하게 해서 구현체를 필요에 따라 선택할 수 있게 설계하는 디자인 패턴
•
같은 기능(interface) 이지만 서로 다른 전략(구현 class)
•
전략 패턴의 장점
◦
코드 중복 방지
◦
런타임시에 타겟 메소드 변경
◦
확장성, 알고리즘 변경이 용이
•
지금까지 수업시간에 적용했던 Strategy 패턴들
클래스이름 | Context | 전략 | 선택 전략 |
ReadLineParser | ReadLineParser | Parser | HospitalParser
PopulationStatisticsParser |
UserDao | .add(), .findById() | ConnectionMaker | AwsConnectionMaker
LocalConnectionMaker
TeacherConnectionMaker |
DeleteAll | .deleteAll() | StatementStrategy | DeleteAllStrategy
AddStrategy
… |
DeleteAllStrategy구현,사용
구현
•
statement를 전략 구조로 설계하기 위해서 인터페이스 생성
public interface StatementStrategy {
PreparedStatement makeStatement(Connection connection) throws SQLException;
}
Java
복사
•
인터페이스를 구현한 클래스 DeleteAllStrategy 생성
public class DeleteAllStrategy implements StatementStrategy{
@Override
public PreparedStatement makeStatement(Connection connection) throws SQLException {
return connection.prepareStatement("delete from user");
}
}
Java
복사
사용
public void deleteAll() throws SQLException {
Connection c = null;
PreparedStatement ps = null;
try {
c = connectionMaker.makeConnection();
ps = stmt.makeStatement(c); //DeleteAllStrategy 사용
ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
}
}
if (c != null) {
try {
c.close();
} catch (SQLException e) {
}
}
}
}
Java
복사
공통로직 jdbcContextWithStatementStrategy분리
•
connection과 preparedStatement부분이 공통으로 들어가기 때문에 메서드로 분리
public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException {
Connection c = null;
PreparedStatement ps = null;
try {
c = connectionMaker.makeConnection();
ps = stmt.makeStatement(c);
ps.executeUpdate();
} catch (SQLException e) {
throw e;
} finally {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
}
}
if (c != null) {
try {
c.close();
} catch (SQLException e) {
}
}
}
}
Java
복사
•
deleteAll()에서 공통 부분 추출했더니 코드가 간결해짐.
public void deleteAll() throws SQLException {
jdbcContextWithStatementStrategy(new DeleteAllStrategy());
}
Java
복사
AddStrategy 추가
구현
•
deleteAll()과 차이점
◦
User클래스의 객체를 생성해서 사용해야한다는 점
◦
RreparedStatement에 인자 3개를 받아와야한다는 점
•
deleteAll()과 공통점
◦
같은 기능을 하는 인터페이스(StatementStrategy)를 가짐
public class AddStrategy implements StatementStrategy{
User user; // User 선언
// 생성자를 통해서 User클래스 받아오기
public AddStrategy(User user) {
this.user = user;
}
@Override
public PreparedStatement makeStatement(Connection connection) throws SQLException {
PreparedStatement pstmt = connection.prepareStatement("INSERT INTO users(id, name, password) VALUES(?,?,?);");
pstmt.setString(1, user.getId());
pstmt.setString(2, user.getName());
pstmt.setString(3, user.getPassword());
return pstmt;
}
}
Java
복사
사용
public void add(User user) throws SQLException {
AddStrategy addStrategy = new AddStrategy(user);
jdbcContextWithStatementStrategy(addStrategy);
}
Java
복사
임학준
전략패턴
UserDao의 메소드에서 .close()를 처리하기 위해try catch문을 사용했다
메소드들의 예외처리 구간이 길고 중복되는 부분이 많아 따로 관리할 필요가 있다.
UserDao의 메소드
전략패턴의 적용
각 메소드에서 변하지 않는 부분(Connection선언, try/catch문…)들은 Context에 해당한다
공통 부분을 제외한 변하는 부분(ex = prepareStatement("delete from users"))을 Strategy에 놓고 각 메소드에 해당하는 부분을 상속받아 ConcreteStrategyA,ConcreteStrategyB에 넣는다 이때 ConcreteStrategy를 선택전략이라 한다
이 구조는 ConnectionMaker인터페이스에서 AwsConnectionMaker와 LocalConnectionMaker를 구현해서 사용하는 방식과 같다
1. 전략
•
UserDao에서 공통된 부분을 제외한 변하는 부분을 전략(인터페이스)으로 정한다
public interface StatementStrategy {
public PreparedStatement makePreParedStatement(Connection connection) throws SQLException;
}
Java
복사
2.선택전략
•
변하는 부분을 선택전략으로 각 메소드에 맞게 구현한다
public class DeleteAllStrategy implements StatementStrategy{
@Override
public PreparedStatement makePreParedStatement(Connection connection) throws SQLException {
return connection.prepareStatement("delete from users");
}
}
Java
복사
public class AddStrategy implements StatementStrategy{
private User user;
public AddStrategy(User user) {
this.user = user;
}
//user를 파라미터로 받는 메소드 add는 User타입 오브젝트를 받을수 있도록 생성자를 이용한다
@Override
public PreparedStatement makePreParedStatement(Connection c) throws SQLException {
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;
}
}
Java
복사
3.컨텍스트 코드
public void jdbcContextWithStatmentStrategy(StatementStrategy stmt) {
Connection c = null;
PreparedStatement ps = null;
try {
c = connectMaker.makeConnection();
ps = stmt.makePreParedStatement(c);//이부분에 선택전략이 들어간다
ps.executeUpdate();
} catch (SQLException e) {
} finally {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
}
}
if (c != null) {
try {
c.close();
} catch (SQLException e) {
}
}
}
}
Java
복사
전략패턴적용후 UserDao의 메소드
조국현
최아영
괄호풀기
Replace로 괄호풀기
Stack으로 괄호풀기
Strategy 패턴
실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다.
StatementStrategy 인터페이스 생성
DeleteAllStrategy
AddStrategy
공통로직 분리