우테코 프리코스 2주차를 복습하면서 다시 풀어보는 과정에서 Car 객체를 외부에서 생성해주는 방식에 대해서 고민하게 되었다.
public class Car {
private String name;
private int distance = 0;
public Car(String name, int distance) {
this.name = name;
this.distance = distance;
}
}
distance는 항상 초깃값이 0인 상태로 생성해줘야한다. 외부에서 객체를 생성할 때는 name값만 제공하면 되는 것이다. 그렇다면 name만 제공했을 때, Car 객체를 생성해주는 방법이 따로 있지 않을까?
정적 팩토리 메서드(static factory method)
정적 팩토리 메서드란 별도의 객체 생성의 역할을 하는 클래스 메서드를 통해 간접적으로 객체를 생성하는 방식이다. 코드를 통해 이해해보자
사실 내가 앞서 문제를 느꼈던 부분은 그냥 생성자로도 구현이 가능하다.
public class Car {
private String name;
private int distance = 0;
public Car(String name, int distance) {
this.name = name;
this.distance = distance;
}
public Car(String name) {
this.name = name;
}
}
정적 팩토리 메서드를 사용하면 다음과 같이 구현할 수 있다.
public class Car {
private String name;
private int distance = 0;
public Car(String name, int distance) {
this.name = name;
this.distance = distance;
}
public static Car distanceZeroFrom(String carName) {
return new Car(carName, 0);
}
}
그렇다면 정적 팩토리 메서드는 생성자 사용을 지양하기 위한 이유로만 사용되는 걸까? 다른 장점은 없을까?
정적 팩토리 메서드의 장점
1. 메서드명을 통해 생성 목적을 설명할 수 있다.
생성자로 객체를 생성할 때는 new 키워드로 생성해줘야한다. 이때 개발자는 생성자의 인자 순서, 내부 구조에 대해 명확히 알고 있어야 목적에 맞게 객체를 생성할 수 있다.
예를 들어, (불공평한 인생처럼) A는 0에서 출발하고, B는 30에서 출발한다고 가정해보자.
생성자를 사용할 때는 아래와 같이 코드를 짤 수 있다.
public class Car {
private String name;
private int distance = 0;
public Car(String name, int distance) {
this.name = name;
this.distance = distance;
}
public Car(String name) {
this.name = name;
}
}
public static void main(String[] args) {
Car A = new Car("kcnsmoothie");
Car B = new Car("BMW", 30);
}
개발자는 A와 B를 생성하기 위해
- 기존 Car 객체에 생성자가 2가지 타입이 있다.
- 첫 번째는 이름과 출발위치를 모두 제시해야한다.
- 두 번째는 이름만 제시하면 되고, 기본 출발 위치는 0으로 설정된다.
다음과 같은 사실을 모두 알고 있어야 한다.
객체가 늘어날수록 개발자의 암기력도 늘어나야한다는 단점이 있다.
정적 팩토리 메서드를 사용하면 다음과 같이 메서드명을 통해 객체 특성을 표현할 수 있어서 코드 가독성이 향상된다!
public class Car {
private String name;
private int distance = 0;
public Car(String name, int distance) {
this.name = name;
this.distance = distance;
}
public static Car distanceZeroFrom(String carName) {
return new Car(carName, 0);
}
public static Car nameDistanceOf(String carName, int distance){
return new Car(carName, 30);
}
}
public static void main(String[] args) {
Car A = Car.distanceZeroFrom("kcnsmoothie");
Car B = Car.nameDistanceOf("BMW", 30);
}
2. 캡슐화의 원칙을 지킬 수 있다.
생성자를 사용하면 외부에 내부의 구현부를 드러내게 된다. 정적 팩토리 메서드를 사용하면 구현부를 숨길 수 있어 캡슐화의 원칙을 지킬 수 있다.
정적 팩토리 메서드 네이밍 규칙
정적 팩토리 메서드는 네이밍 컨벤션이라는 것이 존재한다. 메서드명으로 역할을 명확히 알리고 싶다면 네이밍 컨벤션을 지킨는 것이 좋겠죠? 아무래도
from : 1개의 매개변수
of : 여러 개의 매개변수
getInstance / instance : 인스턴스를 생성
newInstance / create : 새로운 인스턴스를 생성
→ getInstance와 같은 역할을 수행하지만, 매 호출마다 새로운 인스턴스임을 보장한다.
정적 팩토리 메서드의 단점
1. private 생성자일 경우 상속 불가
정적 팩토리 메서드로 객체를 생성을 하게 된다면, 당연하게도 생성자는 캡슐화의 원칙을 지켜주기 위해 private으로 두게 된다. 이때 Class를 상속해 확장하는 것이 어려워진다.
느낀 점
정적 팩토리 메서드에는 다른 장점이랑 단점도 많다. 근데 팩토리 패턴, 싱글톤 패턴 등 다양한 소프트웨어공학적 부분에 대해 좀 더 공부해야 이해할 수 있을 것 같다. 기회가 되면 이펙티브 자바 책도 읽으면서 공부해봐야겠다.
추가로 다음 사항을 공부해봐야겠다.
- 팩토리 메서드
- 추상 팩토리 메서드 패턴
- 인스턴스 캐싱
참고자료
💠 정적 팩토리 메서드 패턴 (Static Factory Method)
Static Factory Method Pattern 정적 팩토리 메서드(Static Factory Method) 패턴은 개발자가 구성한 Static Method를 통해 간접적으로 생성자를 호출하는 객체를 생성하는 디자인 패턴이다. 우리는 지금까지 객체
inpa.tistory.com
https://tecoble.techcourse.co.kr/post/2020-05-26-static-factory-method/
정적 팩토리 메서드(Static Factory Method)는 왜 사용할까?
…
tecoble.techcourse.co.kr