1.4.1 오브젝트 팩토리
기존 코드의 문제점
- 문제의 원인(UserDaoTest)
- Test 수행 클래스
- 어떤 ConnectionMaker 구현 클래스를 사용할지를 결정하는 역할까지 떠맡음(또 다른 책임)
- 해결책
- 관심사의 분리
- UserDao와 ConnectionMaker 구현 클래스의 오브젝트를 생성
- 두 개의 오브젝트를 연결하여 사용될 수 있도록 관계를 맺어주는 클래스 필요
팩토리
팩토리(Factory)
- 객체의 생성 방법을 결정하고, 그렇게 만들어진 오브젝트를 돌려주는 오브젝트
- 오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 분리하려는 목적
DaoFactory.class
- UserDao, ConnectionMaker 생성작업
public class DaoFactory {
/*
* 팩토리의 메소드는 UserDao 타입의 오브젝트를
* 어떻게 만들고, 어떻게 준비시킬지를 결정한다.
*/
public UserDao userDao() {
ConnectionMaker connectionMaker = new DConnectionMaker();
UserDao userDao = new UserDao(connectionMaker);
return userDao;
}
}
UserDaoTest.class
- UserDaoTest는 DaoFactory에 요청해서 만들어진 UserDao 오브젝트를 가져와 사용함
public class UserDaoTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException{
DaoFactory factory = new DaoFactory();
UserDao dao = factory.userDao();
// ...
}
}
설계도로서의 팩토리
책임의 분리
- UserDao / ConnectionMaker
- 데이터 로직 + 기술 로직
- 실질적인 로직을 담당하는 컴포넌트
- 데이터 로직 + 기술 로직
- DaoFactory
- 애플리케이션의 오브젝트를 구성하고 관계를 정의
- 컴포넌트의 구조와 관계를 정의한 설계도
DaoFactory는 소스를 제공함
- N사와 D사는 Daofactory를 수정하여 사용 가능
- 핵심 기술인 UserDao는 소스코드 보존 가능
- DB 연결 방식은 자유로운 확장이 가능함
1.4.2 오브젝트 팩토리의 활용
현재 DaoFactory의 문제점
- 관심은 분리가 되었으나 확장에 유연하지 못함
- UserDao 외 다른 Dao 생성 기능이 생긴다면?
- userDao() 메소드를 복사해서 만들게 되면 오브젝트 생성코드가 매번 반복됨
- ConnectionMaker 구현 클래스가 변경되면 모두 다 바꿔주어야 함
중복으로 인한 문제점 예시
public class DaoFactory {
public UserDao userDao() {
// ConnectionMaker 구현 클래스를 선정하고 생성하는 코드의 중복
ConnectionMaker connectionMaker = new DConnectionMaker();
UserDao userDao = new UserDao(connectionMaker);
return userDao;
}
public AccountDao accountDao() {
// ConnectionMaker 구현 클래스를 선정하고 생성하는 코드의 중복
ConnectionMaker connectionMaker = new DConnectionMaker();
AccountDao accountDao = new AccountDao(connectionMaker);
return accountDao;
}
public MessageDao messageDao() {
// ConnectionMaker 구현 클래스를 선정하고 생성하는 코드의 중복
ConnectionMaker connectionMaker = new DConnectionMaker();
MessageDao messageDao = new MessageDao(connectionMaker);
return messageDao;
}
}
해결책 : 메소드 추출 기법
- ConnectionMaker 구현 클래스를 선정하고 생성하는 코드를 별도의 메소드로 분리
- Dao가 아무리 많아져도 해당 메소드만 수정하면 됨
수정된 DaoFactory.class
public class DaoFactory {
public UserDao userDao() {
return new UserDao(connectionMaker());
}
/*
* 분리해서 중복을 제거한 ConnectionMaker타입 오브젝트 생성 코
*/
public ConnectionMaker connectionMaker() {
return new DConnectionMaker();
}
}
1.4.3 제어권의 이전을 통한 제어의 역전
제어의 역전
- 제어의 역전 : 프로그램의 제어 흐름 구조가 뒤바뀌는 것
- 일반적인 프로그램의 흐름
- main() 메소드 등 프로그램의 시작
- 다음에 사용할 오브젝트를 결정
- 결정한 오브젝트의 생성
- 만들어진 오브젝트의 메소드 호출
- 해당 오브젝트 메소드 내에서 다음에 사용할 것은 결정하고 호출
- 반복
- 각 오브젝트는 프로그램의 흐름을 결정하거나 사용할 오브젝트를 구성하는 작업에 능동적으로 참여
- 제어의 역전에서는 오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않음
- 모든 제어 권한을 다른 대상에게 위임
- main() 등의 엔트리 포인트를 제외하면 모든 오브젝트는 위임받은 제어 권한을 갖는 특별한 오브젝에 의해 결정되고 만들어짐
UserDao와 DaoFactory
- ConnectionMaker의 구현 클래스 결정 및 오브젝트 생성 제어권 : UserDao -> DaoFactory
- UserDao, ConnectionMaker는 수동적인 존재로 바뀜
- UserDao, ConnectionMaker 자신도 DaoFactory에 의해 생성됨
- 자신이 사용할 오브젝트(ConnectionMaker)도 DaoFactory에게 공급받아 수동적으로 사용
- DaoFactory : 가장 단순한 IoC 컨테이너 / IoC 프레임워크
' Spring > 토비의 스프링 3.1' 카테고리의 다른 글
1.6 싱글톤 레지스트리와 오브젝트 스코프 (0) | 2019.01.09 |
---|---|
1.5 스프링의 IoC (0) | 2019.01.07 |
1.3 DAO의 확장 (0) | 2019.01.07 |
1.2 DAO의 분리 (0) | 2019.01.03 |
1.1 초난감 DAO (0) | 2019.01.03 |