클라이언트에서 인스턴스를 얻는 전통적인 수단은 public 생성자를 만드는 것입니다.
하지만 모든 프로그래머가 꼭 알아둬야 할 기법이 하나 더 있다.
바로 정적 팩토리 메서드이다.
정적 팩터리 메서드가 생성자보다 좋은 장점을 먼저 알아보자
- 이름을 가질 수 있다.
public StaticFactoryMethodA(String name) {
this.name = name;
}
//vs
public static StaticFactoryMethodA CreateStaticFactoryMethod(String name) {
StaticFactoryMethodA staticFactoryMethodA = new StaticFactoryMethodA();
staticFactoryMethodA.name = name;
return staticFactoryMethodA;
}
// 이름을 가질 수 있기에 어떤 일을 하는지 정확하게 파악 할 수 있다.
생성자 자체는 반환될 객체의 특성을 제대로 설명하지 못한다.
반면 정적 팩토리는 이름만 잘 지으면 반환될 객체의 특성을 쉽게 묘사할 수 있다.
- 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
// second . 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
private static final StaticFactoryMethodA STATIC_FACTORY_METHOD = new StaticFactoryMethodA();
private StaticFactoryMethodA(){}
public static StaticFactoryMethodA getNewInstance() {
return STATIC_FACTORY_METHOD;
}
// Test Code 참조
@Test
void getNewInstance() {
StaticFactoryMethodA staticFactoryMethodA = StaticFactoryMethodA.getNewInstance();
StaticFactoryMethodA staticFactoryMethodA2 = StaticFactoryMethodA.getNewInstance();
System.out.println("(staticFactoryMethod == staticFactoryMethod2) = " + (staticFactoryMethodA == staticFactoryMethodA2));
//(staticFactoryMethod == staticFactoryMethod2) = true
}
생성자는 private로 제한하고 정적 팩토리 메서드로 인스턴스를 반환해주면 싱글턴을 유지할 수 있을뿐만 아니라 메서드 내에서 인스턴스 자체를 통제 할 수있다.
- 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
이 능력은 반환할 객체의 클래스를 자유롭게 선택할 수 있게 하는 '엄청난 유연성'을 선물한다.
아래
static class CARD{
public static final String SAMSUNG_CARD = "삼성";
public static final String KAKAO_CARD="카카오";
static Payment payment(String card){
switch (card){
case SAMSUNG_CARD:
// 3. 반환 타입의 하위타입 객체를 반환할 수 있는 능력이 있다.
return new SamSungPayment();
case KAKAO_CARD:
return new KakaoPayment();
}
throw new IllegalArgumentException();
}
}
Payment라는 상위 타입 Interface로 하위 타입인 SamSungPayment 클래스를 숨김으로써
프로그래머는 *인터페이스대로 동작할 객체를 얻을 것을 알기에 * 굳이 SamSungPayment.class를 찾아가서 알아보지 않아도 된다.
- 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
세번째와 유사한 내용이며 유연하게 대응 가능하다는 점이다.
public abstract class StaticFactoryMethodB {
// fourth . 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환 할 수 있다.
abstract void getName();
public static StaticFactoryMethodB getNewInstance(String code) {
StaticFactoryMethodB staticFactoryMethodB = null;
if (code.indexOf("2") == 1) {
staticFactoryMethodB = new Point();
} else {
staticFactoryMethodB = new Coupon();
}
return staticFactoryMethodB;
}
}
class Coupon extends StaticFactoryMethodB {
public void getName() {
System.out.println("쿠폰을 발행합니다");
}
}
class Point extends StaticFactoryMethodB {
public void getName() {
System.out.println("포인트를 1000점 적립합니다");
}
}
위와 같이 받는 code 값에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
- 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
public abstract class StaticFactoryMethodC {
// fifth . 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
public abstract void getName();
public static StaticFactoryMethodC getNewInstance() {
StaticFactoryMethodC staticFactoryMethodC = null;
try {
Class<?> aClass = Class.forName("prac.effectivejava.chapter2.item1.staticfactorymethod.StaticFactoryMethodChild");
staticFactoryMethodC = (StaticFactoryMethodC) aClass.getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException e) {
System.out.println("클래스가 없습니다");
} catch (InstantiationException e) {
System.out.println("메모리에 올릴 수 없습니다.");
} catch (IllegalAccessException e) {
System.out.println("클래스파일 접근 오류입니다.");
} catch (InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
return staticFactoryMethodC;
//Test 참조
}
}
public class StaticFactoryMethodChild extends StaticFactoryMethodC {
@Override
public void getName() {
System.out.println("정상 로드 되었습니다.");
}
}
TEST CODE
class StaticFactoryMethodChildTest {
@Test
void getName() {
StaticFactoryMethodC staticFactoryMethodC = StaticFactoryMethodC.getNewInstance();
staticFactoryMethodC.getName();
//정상 로드 되었습니다.
}
}
"이 포스팅은 위 책을 참고하여 작성되었습니다."
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
GitHub - Kimjunghwoi/effectiveJava: 이펙티브 자바를 읽고 정리합니다.
이펙티브 자바를 읽고 정리합니다. Contribute to Kimjunghwoi/effectiveJava development by creating an account on GitHub.
github.com
'개발자 공부 업무 정보 > JAVA' 카테고리의 다른 글
Spring Security 소개 및 적용 방법 (0) | 2023.11.17 |
---|---|
정적 팩터리 메서드란? (0) | 2022.12.14 |
Random 보단 SecureRandom (0) | 2022.10.19 |
java request 안의 모든 parameter 확인하기 (0) | 2020.02.18 |
[JAVA] - 숫자 각 자리수의 합 구하기 (0) | 2019.01.17 |