본문 바로가기
test & refactoring

[테스트 & 리팩토링 6편] 팩토리 패턴 if else 줄이기 (map, functional interface 사용)

by 무대포 개발자 2022. 8. 1.
728x90
반응형

source 는 Github 에 있습니다.

목차는 테스트 & 리팩토링 목차 에 있습니다.

[테스트 & 리팩토링 6편] 팩토리 패턴 if else 줄이기 (map, functional interface 사용)

팩토리 패턴이란?

  • 객체를 생성해주는 패턴 중 하나 입니다.

  • 객체를 생성하는 인터페이스를 미리 정의하고, 인스턴스를 만들 클래스의 결정을 서브 클래스에서 결정합니다.

  • 아래 소스는 팩토리 패턴으로 구현한 소스이며, 리팩토링 전입니다.

public class FactoryPatternExample {
public static void main(String[] args) {
Sport sport = getSport(SportTypeCd.SOCCER);
sport.play();
}
public static Sport getSport(SportTypeCd sportTypeCd) {
if (SportTypeCd.BASEBALL.equals(sportTypeCd)) {
return new Baseball();
} else if (SportTypeCd.SOCCER.equals(sportTypeCd)) {
return new Soccer();
} else {
throw new IllegalArgumentException(String.format("invalid sportTypeCd : ", sportTypeCd));
}
}
@Getter
@RequiredArgsConstructor
private enum SportTypeCd {
SOCCER("SOCCER", "축구"),
BASEBALL("BASEBALL", "야구")
;
private final String code;
private final String desc;
}
}

If else 를 줄이는 방법

  • 아래와 같이 Map 에 집어넣고 데이터를 가져온다면 if else 를 줄일 수 있습니다.
public class FactoryPatternRefactoringExample {
private static Map<SportTypeCd, Sport> map = new HashMap<>();
static {
map.put(SportTypeCd.SOCCER, new Soccer());
map.put(SportTypeCd.BASEBALL, new Baseball());
}
public static void main(String[] args) {
Sport sport = getSport(SportTypeCd.SOCCER);
sport.play();
}
public static Sport getSport(SportTypeCd sportTypeCd) {
return map.get(sportTypeCd);
}
@Getter
@RequiredArgsConstructor
private enum SportTypeCd {
SOCCER("SOCCER", "축구"),
BASEBALL("BASEBALL", "야구")
;
private final String code;
private final String desc;
}
}

interface 구현 없이 Functional interface 사용

  • Supplier functional interface 는 매개변수 없이 T 를 리턴합니다.
    • T get()
public class FactoryPatternRefactoring_v2_Example {
public static void main(String[] args) {
SportInstance sportInstance = SportInstance.findSportInstance(SportInstance.SOCCER.getCode());
System.out.println(sportInstance.getSupplier().get());
}
@Getter
private enum SportInstance {
SOCCER("SOCCER", () -> "play soccer..."),
BASEBALL("BASEBALL", () -> "play baseball..."),
;
private static Map<String, SportInstance> instanceMap =
Arrays.stream(SportInstance.values()).collect(Collectors.toMap(o -> o.getCode(), o -> o));
private String code;
private Supplier<String> supplier;
SportInstance(String code, Supplier supplier) {
this.code = code;
this.supplier = supplier;
}
private static SportInstance findSportInstance(String sportTypeCd) {
return Optional.ofNullable(instanceMap.get(sportTypeCd))
.orElseThrow(IllegalArgumentException::new);
}
}
}

댓글