모든 오브젝트는 변하지만 모두 동일한 방식으로 변하는 것은 아니다.
ex. 데이터 액세스 로직을 어떻게 만들 것인가 vs DB 연결을 어떤 방법으로 할 것인가
변화의 이유와 시기, 주기 등이 다르다.
NUserDAO
, DUserDao
코드는 변하지 않는다.두 개의 관심사를 본격적으로 독립시키며 손쉽게 확장시키기
package user.domain;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SimpleConnectionMaker {
public Connection makeNewConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection c = DriverManager.getConnection("jdbc:mysql://localhost/toby_spring", "root",
"0000");
return c;
}
}
...
public abstract class UserDao {
private SimpleConnectionMaker simpleConnectionMaker;
public UserDao(){
simpleConnectionMaker = new SimpleConnectionMaker();
}
public void add(User user) throws ClassNotFoundException, SQLException {
Connection c = simpleConnectionMaker.makeNewConnection();
...
public class DUserDao extends UserDao{
@Override
public Connection getConnection() throws ClassNotFoundException, SQLException {
// D 사에서 사용하는 DB connection 생성 코드
Class.forName("com.mysql.cj.jdbc.Driver");
Connection c = DriverManager.getConnection("jdbc:mysql://localhost/toby_spring", "root", "0000");
return c;
}
UserDao 가 SimpleConnectionMaker 에 종속된다.(p. 74)
→ 상속할 때 UserDao 코드 수정 없이 DB 커넥션 생성 기능 변경 불가
기능 분리 전 서브 클래스에서 사용하던 connection 생성 메서드가 openConnection() 이었다면?
→ UserDao 클래스의 add(), get() 메소드의 커넥션을 가져오는 코드를 일일이 변경해야 한다.
Connection c = simpleConnectionMaker.`makeNewConnection`(); (Before)
Connection c = simpleConnectionMaker.`openConnection`(); (After)
DB 커넥션을 제공하는 클래스가 어떤 것인지를 UserDao 가 구체적으로 알고 있어야 한다.
근본적인 원인: UserDao 가 바뀔 수 있는 정보, DB 커넥션을 가져오는 클래스에 대해 너무 많이 알고 있다.
- 어떤 클래스가 사용될지
- 그 클래스에서 커넥션을 가져오는 메서드의 이름이 무엇인지 …
클래스를 분리하면서 문제해결하기: 두 개의 클래스가 서로 긴밀하게 연결되지 않도록 중간에 추상적인 느슨한 연결고리 생성