학습 요약
- 정적 팩터리 메서드 ( static factory method) 란?
- 정적 팩터리 메서드가 생성자보다 좋은 장점 다섯가지
- 정적 팩터리 메서드가 생성자보다 좋지않은 장점 두가지
정적 팩터리 메서드 ( static factory method) 란?
클래스의 인턴스를 얻는 전통적인 public 생성자가 아닌 객체 생성의 역할을 하는 클래스 메서드라는 의미로 요약해 볼 수 있다. 다시 말해 new 키워드가 아닌 해당 클래스의 메서드로 객체생성을 할 수 있다.
정적 팩터리 메서드가 생성자보다 좋은 장점 다섯가지
1. 이름을 가질 수 있다.
- 생성자에 넘기는 매개변수와 생성자 자체 만으로는 반활될 객체의 특성을 제대로 설명하지 못한다. 하지만 정적 팩터리는 클래스와 다른 이름을 지을수 있기 때문에 이름만 잘 지으면 객체의 특성을 조금 더 쉽게 사용자 에게 알려줄 수 있다. 책에서 나오는 예제는 BigInteger 클래스 이다. 조금 더 정확한 이해를 위해서 실제 BigInteger의 생성자를 살펴보자
자 이렇게만 보고 내가 BigInteger를 처음 사용한다면 ... 아니 오랜만에 사용 한다면 이름이 같은 생성자 중에서 내가 사용하고 싶은 생성자가 어떤것 인지 알 수 없다. 그래서 책에서는 소수값을 반환하는 생성자와 팩터리메소드를 비교하면서 설명해 준다.
BigInteger(int bitLength, int certainty, Random rnd); 생성자
BigInteger.probablePrime(int bitLength, Random rnd) 정적 팩터리 메소드
사용자가 BigInteger.probablePrime 을 보는순간 메소드 명에서 어느정도의 감을 잡을 수 있기 때문에 반환되는 객체의 특성을 예측하기 쉬워진다.
2. 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
- 반복되는 요청에 같은 객체를 반환하는 식으로 정적 팩터리 방식의 클래스는 언제 어느 인스턴스를 살아 있게 할지를 철저하게 통제할 수 있다. 이런 클래스를 인스턴스 통제(instance-controlled) 클래스라 한다. 이렇게 통제를 통해 싱글톤이나 인스턴스화 불가 클래스를 만들수 있고 생성 비용이 큰 객체의 반복적인 생성을 피할수 있다.
3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
- 이 능력은 반환할 객체의 클래스(리턴 타입의 상속을 받은 모든 클래스 가능)를 자유롭게 선택할 수 있게 하는 엄청난 유연성을 선물한다.
반환할 객체의 자유도를 높일 수 있기에 원하는 객체를 리턴 할 수 있습니다. 만약 특정 코드를 받아 코드에 따른 반환 객체를 자신 하위 타입 중 선택하게 한다면 아래와 같이 쉽게 처리할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public abstract class StaticFactoryMethod {
abstract void getName();
public static StaticFactoryMethod getNewInstance( String code ) {
StaticFactoryMethod staticFactoryMethod = null;
if( code.indexOf("2") == 1 ) {
staticFactoryMethod = new Point();
} else {
staticFactoryMethod = new Coupon();
}
return staticFactoryMethod;
}
}
class Coupon extends StaticFactoryMethod {
public void getName() {
System.out.println("쿠폰을 발행합니다.");
}
}
class Point extends StaticFactoryMethod {
public void getName() {
System.out.println("포인트 1000점을 적립합니다.");
}
}
|
cs |
1
2
3
4
5
6
|
public static void main(String args[]){
StaticFactoryMethod staticFactoryMethod = StaticFactoryMethod.getNewInstance("223123");
StaticFactoryMethod staticFactoryMethod1 = StaticFactoryMethod.getNewInstance("123123");
staticFactoryMethod.getName();
staticFactoryMethod1.getName();
}
|
cs |
// 결과출력
쿠폰을 발행합니다.
포인트 1000점을 적립합니다.
4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
- 반환타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다. 같은 이름의 메서드지만 매개변수의 개수에 따라 리턴받는 클래스를 아무 하위타입 클래스를 리턴 받을 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public abstract class StaticFactoryMethodType {
public abstract void getName();
static public StaticFactoryMethodType getNewInstance( String code ) {
return new OneClass();
}
static public StaticFactoryMethodType getNewInstance( String code, String name ) {
return new TwoClass();
}
}
class OneClass extends StaticFactoryMethodType {
public void getName() {
System.out.println("쿠폰을 발행합니다.");
}
}
class TwoClass extends StaticFactoryMethodType {
public void getName() {
System.out.println("포인트 1000점을 적립합니다.");
}
}
|
cs |
1
2
3
4
5
6
|
public static void main(String args[]){
StaticFactoryMethod staticFactoryMethod = StaticFactoryMethod.getNewInstance("223123");
StaticFactoryMethod staticFactoryMethod1 = StaticFactoryMethod.getNewInstance("123123");
staticFactoryMethod.getName();
staticFactoryMethod1.getName();
}
|
cs |
// 결과출력
쿠폰을 발행합니다.
포인트 1000점을 적립합니다.
5. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
- 장점 3, 4와 관련된 유연함에 관한 내용으로 메서드 안에서 객체를 반환할 때, 당장 클래스가 존재하지 않아도 특정 텍스트 파일에서 인터페이스 구현체의 위치를 알려주는 곳의 정보를 가지고 해당 객체를 읽어 생성할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package algorithm.dataStructure;
public abstract class StaticFactoryMethodType {
public abstract void getName();
public static StaticFactoryMethodType getNewInstance() {
StaticFactoryMethodType temp = null;
try {
Class<?> childClass = Class.forName("algorithm.dataStructure.StaticFactoryMethodTypeChild");
temp = (StaticFactoryMethodType) childClass.newInstance();
}catch (ClassNotFoundException e) {
System.out.println("클래스가 없습니다.");
} catch (InstantiationException e) {
System.out.println("메모리에 올릴수 없습니다.");
} catch (IllegalAccessException e) {
System.out.println("클래스파일 접근 오류입니다.");
}
return temp;
}
}
|
cs |
1
2
3
4
5
6
7
8
9
10
|
package algorithm.dataStructure;
public class StaticFactoryMethodTypeChild extends StaticFactoryMethodType {
@Override
public void getName() {
System.out.println("정상 로드 되었습니다");
}
}
|
cs |
1
2
3
4
5
|
public static void main(String args[]){
StaticFactoryMethodType staticFactoryMethodType = StaticFactoryMethodType.getNewInstance();
staticFactoryMethodType.getName();
}
|
cs |
// 결과출력
정상 로드 되었습니다
정적 팩터리 메서드가 생성자보다 좋지않은 단점 두가지
1. 상속을 하려면 public 이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
2. 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.
'Effective Java > 객체 생성과 파괴' 카테고리의 다른 글
#03 #02의 보충설명 - 계층적으로 설계된 클래스와 빌더패턴 (1) | 2021.05.31 |
---|---|
#02 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2021.05.26 |