✏️10.4 조건부 로직을 다형성으로 바꾸기 (Replace Conditional with Polymorphism)
리팩터링 전
switch (bird.type) {
case '유럽 제비':
return "보통이다";
case '아프리카 제비':
return (bird.numberOfCoconuts > 2) ? "지쳤다" : "보통이다";
case 'NorwegianBlueParrot':
return (bird.voltage > 100) ? "그을렸다" : "예쁘다";
default:
return "알 수 없다";
리팩터링 후
class EuropeanSwallow {
get plumage() {
return "보통이다";
}
...
class AfricanSwallow {
get plumage() {
return (this.numberOfCoconuts > 2) ? "지쳤다" : "보통이다";
}
...
class NorwegianBlueParrot {
get plumage() {
return (this.voltage > 100) ? "그을렸다" : "예쁘다";
}
🧷 배경
조건문을 클래스와 다형성을 이용하면 더 확실하게 분리할 수 있다.
기본 로직을 슈퍼클래스로 넣어서 서브클래스의 변형 동작에 신경 쓰지 않고 기본에 집중하게 할 수 있게 한다.
🧷 절차
다형적 동작을 표현하는 클래스들이 아직 없다면 만들고 팩터리 함수도 함께 만든다.
호출하는 코드에서 팩터리 함수를 사용하게 한다.
조건부 로직 함수를 슈퍼클래스로 옮긴다.
서브클래스 중 하나를 선택하여, 슈퍼클래스의 조건부 로직 메서드를 오버라이드한다.
같은 방식으로 각 조건절을 해당 서브클래스에서 메서드로 구현한다.
슈퍼클래스 메서드에는 기본 동작 부분만 남긴다.
🧷 예시
🧷 리팩터링 전
function plumages(birds) {
return new Map(birds.map((b) => [b.name, plumage(b)]));
}
function speeds(birds) {
return new Map(birds.map((b) => [b.name, airSpeedVelocity(b)]));
}
function plumage(bird) {
switch (bird.type) {
case '유럽 제비':
return '보통이다';
case '아프리카 제비':
return bird.numberOfCoconuts > 2 ? '지쳤다' : '보통이다';
default:
return '알 수 없다';
}
}
function airSpeedVelocity(bird) {
switch (bird.type) {
case '유럽 제비':
return 35;
case '아프리카 제비':
return 40 - 2 * bird.numberOfCoconuts;
default:
return null;
}
}
🧷 리팩터링 후
function plumages(birds) {
return new Map(birds
.map((b) => createBird(b))
.map((bird) => [bird.name, bird.plumage]));
}
function speeds(birds) {
return new Map(birds
.map((b) => createBird(b))
.map((bird) => [bird.name, bird.airSpeedVelocity]));
}
class Bird {
constructor(birdObject) {
Object.assign(this, birdObject);
}
get plumage() {
return '알 수 없다';
}
get airSpeedVelocity() {
return null;
}
}
class EuropeanSwallow extends Bird {
get plumage() {
return '보통이다';
}
get airSpeedVelocity() {
return 35;
}
}
class AfricanSwallow extends Bird {
get plumage() {
return this.numberOfCoconuts > 2 ? '지쳤다' : '보통이다';
}
get airSpeedVelocity() {
return 40 - 2 * this.numberOfCoconuts;
}
}
function createBird(bird) {
switch (this.type) {
case '유럽 제비':
return new EuropeanSwallow(bird);
case '아프리카 제비':
return new AfricanSwallow(bird);
default:
return new Bird(bird);
}
}
Previous10.3 중첩 조건문을 보호 구문으로 바꾸기 (Replace Nested Conditional with Guard Clauses)Next10.5 특이 케이스 추가하기 (Introduce Special Case)
Last updated