지난 포스팅에서는
관심사 분리를 메소드가 아닌
클래스로 해보았다.
하지만 여전히 확장성에
문제가 발생했다.
확장을 하려면 '추상화'를 해야한다.
추상화란, 구현 클래스 간의
공통된 특징을 하나로 묶는 것을 의미한다.
그래서 이전 포스팅에서는
관심사 확장을 위해
'추상 클래스'를 이용하였다.
그러나
추상 클래스는 '상속'을 통하여
추상 클래스와 구현 클래스 간의
관계가 설정된다.
상속은 결합력이 강해 서로 종속된다.
이런 문제를 해결하기 위해,
느슨한 결합을 제공하는
'인터페이스'를 사용한다.
인터페이스
인터페이스는 어떤 일을 하겠다만 정의하고 정확한 구현 방법은 정의하지 않는다. 그러므로 인터페이스와 관계를 맺는 클래스는 구체적인 구현 방법은 신경쓰지 않아도 된다. 그저 인터페이스 객체가 어떤 일을 하는지만 알면 된다. 이것을 '느슨한 결합'이라 부른다.
구체적인 구현 방법은 인터페이스를 구현한(implements) 클래스의 일이다.
지난 포스팅에 이어 UserDao를 살펴보자.
UserDao 클래스
public class UserDao {
private ConnectionMaker connectionMaker; // 인터페이스 객체
public UserDao( ) {
connectionMaker = new AConnectionMaker(); // A사 커넥션 구현 객체 생성
}
public int add(User user) throws SQLException {
Connection c = connectionMaker.makeNewConnection();
//생략...
}
public User get(String UserId) throws SQLException {
Connection c = connectionMaker.makeNewConnection();
//생략....
}
}
UserDao 클래스는 그저 인터페이스 참조변수만 활용하면 된다. 만약 A사가 아닌 B사의 커넥션 구현 객체로 변경할 생각이면, connectionMaker = new AConnectionMaker(); 이 부분만 변경하면 된다. 인터페이스 구현 클래스는 인터페이스의 기능을 동일하게 구현하고 있기에 변경되어도 문제 없다. 이를 객체의 '부품화'라고 한다.
ConnectionMaker 인터페이스
public interface ConnectionMaker {
public Connection makeNewConnection();
}
A사 구현 클래스
public class AConnectionMaker implements ConnectionMaker {
@Override
public Connection makeNewConnection() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/SpringProject";
String id = "root";
String pw = "111111";
Connection c = DriverManager.getConnection(url, id, pw);
System.out.println("A사 커넥션 접근 객체 생성");
return c;
} catch (ClassNotFoundException e) {
System.out.println("클래스 발견 못함");
} catch (SQLException e) {
System.out.println("DB 접속 실패");
}
return null;
}
}
B사 구현 클래스
public class BConnectionMaker implements ConnectionMaker {
@Override
public Connection makeNewConnection() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/SpringProject";
String id = "root";
String pw = "111111";
Connection c = DriverManager.getConnection(url, id, pw);
System.out.println("B사 커넥션 접근 객체 생성");
return c;
} catch (ClassNotFoundException e) {
System.out.println("클래스 발견 못함");
} catch (SQLException e) {
System.out.println("DB 접속 실패");
}
return null;
}
}
만약 변경사항이 발생하면, 구현클래스만 수정하면 된다. 커넥션과 UserDao 클래스는 완전히 분리되어 있기에 커넥션 구현 클래스가 변경되어도 어떤 코드도 수정할 필요가 없다. 그러나 단 한 가지 경우, 불가피하게 수정해야 한다. 구현 클래스를 바꾸는 경우 수정해야 한다.
A사 구현 클래스를 사용하다가 B사 구현 클래스로 변경하려면 UserDao 클래스를 변경해야한다. 이 또한 일종의 '종속'이다. UserDao 클래스와 커넥션 관심사를 가진 클래스간의 완전한 분리를 할 수 있는 방법은 없을까? 다음 포스팅에서 이에 관해 다루어 보겠다.
참고문헌
'SPRING > Spring Basic' 카테고리의 다른 글
[스프링] 프레임워크란 무엇인가? ( 제어의 역전 (IOC) ) (2) | 2021.08.03 |
---|---|
[스프링] 관심사의 분리 ( 관계설정 책임의 분리 ) (0) | 2021.07.26 |
[스프링] 관심사의 분리 ( 클래스의 분리 ) (0) | 2021.07.22 |
[스프링] 관심사의 확장 ( 추상클래스 ) (0) | 2021.07.21 |
[스프링] 관심사의 분리 ( 메소드 분리 ) (0) | 2021.07.20 |