/* UserDao.java */
package lecture0722.step3;
public class UserDAO {
private SimpleConnectionMaker simpleConnectionMaker;
public UserDAO(){
simpleConnectionMaker = new SimpleConnectionMaker();
// ...생략...
public void insert(User user) throws ClassNotFoundException, SQLException {
// try - catch를 사용하지 않아요! (다른 곳에서 에러 처리)
Connection con = simpleConnectionMaker.makeConnection();
...
}
/* SimpleConnectionMaker.java */
public class SimpleConnectionMaker {
public Connection makeNewConnection() throws ClassNotFoundException, SQLException{
Class.forName("com.mysql.cj.jdbc.Driver");
String jdbc_url = "jdbc:mysql://localhost:3306/sqldb?charEncoding=UTF-8&serverTimezone=UTC&userSSL=false";
Connection con = DriverManager.getConnection(jdbc_url,"root","test1234");
return con;
}
}
- 위의 코드는 코드는 잘 분리하였지만, 소스코드를 공개하지 않은 이상 재사용이 힘들다..
- UserDAO 안에 simpleConnectionMaker가 private으로 정의되어 있어, 클래스가 tightly coupled되는 현상이 발생한다. (더 안좋아짐)
UserDAO는 simpleConnectioMaker가 없으면 작동하지 않는다..
- 한 클래스 안에 다른 클래스 이름이 명확하게 박히면 좋지 않다. (Java 기본 API 제외)
interface를 구현해서 tightly coupled되는 현상을 줄여준다.
public interface ConnectionMaker {
public Connection makeConnection() throws ClassNotFoundException, SQLException;
}
public class NUserDAO implements ConnectionMaker {
@Override
public Connection makeConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
String jdbc_url = "jdbc:mysql://localhost:3306/sqldb?charEncoding=UTF-8&serverTimezone=UTC&userSSL=false";
Connection con = DriverManager.getConnection(jdbc_url,"root","test1234");
return con;
}
}
private ConnectionMaker connectionMaker;
public UserDAO(){
// UserDAO 안에 아직 만들지 않은 클래스를 넣어야 한다. (이 부분이 문제)
// 오브젝트 간의 의존관계를 밀어버리는 것 - 코드 내에서 해결이 안된다.
connectionMaker = new NUserDAO();
}
위 코드는 한 클래스 (UserDAO)에 인터페이스 구현 클래스 (NUserDAO)가 들어가 있는 형태로, 두 클래스 간의 의존성이 강하다.
객체지향에서 클래스 간의 의존성을 떨어트리는 것이 좋다.
private ConnectionMaker connectionMaker;
// 객체를 주입받아요(DI)
public UserDAO(ConnectionMaker connectionMaker){
// 위 인터페이스를 구현한 객체를 파라미터로 받아서
// 직접 DAO 안에서 객체를 만들지 않고, 받아와서 사용한다
// 클래스 내에서 다른 클래스 이름이 나오지 않는다
// Main으로 이동 -> 객체를 인자로 넣어주어야 한다
this.connectionMaker = connectionMaker;
}
public void insert(User user) throws ClassNotFoundException, SQLException {
// try - catch를 사용하지 않아요! (다른 곳에서 에러 처리)
Connection con = connectionMaker.makeConnection();
...
public class NUserDAO implements ConnectionMaker {
@Override
public Connection makeConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.cj.jdbc.Driver");
String jdbc_url = "jdbc:mysql://localhost:3306/sqldb?charEncoding=UTF-8&serverTimezone=UTC&userSSL=false";
Connection con = DriverManager.getConnection(jdbc_url,"root","test1234");
return con;
}
}
public class Main {
public static void main(String[] args) throws ClassNotFoundException, SQLException{
// Service없이 main에서 직접 로직처리를 해보아요!
// 인터페이스를 구현한 객체를 만들어 준다.
ConnectionMaker connectionMaker = new NUserDAO();
UserDAO dao = new UserDAO(connectionMaker);
...
- 위 코드는 인터페이스 구현 객체를 생성자 함수에 주입시킴으로써 클래스 간 결합도를 낮춰준다.
- 즉, 두 개의 클래스 간의 의존성은 없다.
- 여기서 클래스 간의 의존성은 클래스에 새로운 클래스가 박혀있는 상태로 되어 있다.
- UserDAO 객체와 NUerDAO 객체가 서로 사용될 때, 객체 의존성이 존재하게 된다.
- 즉, runtime 의존성을 가지게 된다.
- 클래스 간 의존성은 약해지고, 한 객체에 다른 객체를 인자로 받게 되면서 객체 의존성이 생기게 된다.
결론 - UserDAO는 다른 class에 종속되지 않아요!