CastleJo의 개발일지

Move Creation Knowledge to Factory (110)

|

개요

어떤 클래스의 인스턴스를 생성하는 데 사용되는 데이터와 코드가 여러 클래스에 퍼져있다면,
그 생성 지식을 하나의 팩터리 클래스로 옮긴다.


동기

객체 생성을 위한 지식이 여러 클래스에 퍼져 있을 때, 이를 문어발 생성 이라고 한다. 이 것은 객체 생성과 상관 없는 클래스가 그 책임의 일부를 맡고 있음을 뜻한다.
예를 들어 클라이언트가 주어진 외부 설정값에 맞춰 객체의 상태를 조정할 필요가 있지만, 그 객체의 생성을 담당하는 코드에는 쉽게 접근할 수 없는 경우를 생각해보자. 클라이언트에서 객체 생성 코드에 쉽게 접근할 수 없다면 클라이언트가 어떻게 그 객체의 상태를 조정할 수 있을 것인가? 보통은 무식한 방법으로 해결한다. 클라이언트는 외부 설정값을 한 객체에 전달하고, 이를 또 다른 객체로, 결국에는 생성 코드까지 계속 전달하는 것이다. 이렇게 하는 것이 가능은 하지만, 생성 코드와 데이터가 여러 곳에 퍼지는 문제가 있다.
이 경우 Factory 패턴이 도움이 된다. 팩토리 인스턴스가 런타임에서 계속 재사용되며 추가기능을 부여할 수도 있다.

장점
  • 생성 로직과 외부 설정값 처리 로직을 한 곳으로 모은다.
  • 생성 로직으로부터 클라이언트를 분리한다.
단점
  • 직접 생성으로도 충분한 경우라면, 괜히 설계만 복잡하게 한다.


절차

이 절차는 팩터리를 인터페이스가 아닌 클래스로 구현한다고 가정한다. 다른 클래스에서 구현할 팩터리 인터페이스가 필요하다면, 이 절차를 조금 수정해야 한다.

  1. 주어진 클래스의 인스턴스를 생성하기 위해 다른 클래스와 협력하는 클래스를 찾는다. 이런 클래스를 생성 클래스라 하고 인스턴스로 만들어지는 클래스를 대상 클래스 라고 하자. 만약 생성 클래스가 대상 클래스의 인스턴스를 만들 때 생성 메서드를 통하지 않는다면 필요할 경우 생성 클래스나 대상 클래스를 수정해 생성 메서드를 사용하도록 한다.

  2. 팩터리로 사용할 클래스를 만드는데, 그 이름은 대상 클래스를 고려하여 짓는다

  3. Move Method 리팩터링을 적용해 생성 메서드를 팩터리 클래스로 옮긴다. 생성 메서드가 static이라도 옮긴 후에는 인스턴스 메서드로 바꿀 수 있다.

  4. 팩터리의 인스턴스를 만들고, 이를 통해 대상 클래스의 인스턴스를 얻도록 생성 클래스를 수정한다.

  5. 다른 클래스의 데이터와 메서드가 여전히 생성 작업에 사용되고 있을 수 있다. 무엇이든 팩토리에 있는 것이 더 나아보인다면 팩토리로 옮겨 더 많은 기능을 담당하게 할 수 있다.


구현