개요
서브클래싱은 원래 데이터 구조와 다른 변종 또는 종류에 따라 다르게 동작하게 할 수 있는 유용한 메커니즘이나, 더 이상 사용이 안된다면 제거하는 것이 최선
예시
class Person{ constructor(name){ this._name = name; } get name(){return this._name;} get genderCode(){return "X";} } class Male extends Person{ get genderCode(){return "M";} } class Female extends Person{ get genderCode(){return "F";} } //클라이언트 const numberOfMales = people.filter(p=>p instanceof Male).length; |
//직관적으로 생성자 마다 팩터리 메서드를 만들 경우 function createPerson(name){ return new Person(name); } function createMale(name){ return new Male(name); } function createFemale(name){ return new Female(name); } //결국, 리팩터링하면 큰 의미가 없다. function loadFromInput(data){ const result = []; data.forEach(aRecord=>{ let p; switch (aRecord.gender){ case 'M' : p = new Male(aRecord.name); break; case 'F' : p = new Female(aRecord.name); break; default : p = new Person(aRecord.name); } result.push(p); }); return result; } |
//생성할 클래스를 선택하는 로직을 함수로 추출하는 것이 더 낫다. function createPerson(aRecord){ let p; switch (aRecord.gender){ case 'M' : p = new Male(aRecord.name); break; case 'F' : p = new Female(aRecord.name); break; default : p = new Person(aRecord.name); } return p; } function loadFromInput(data){ const result = []; data.forEach(aRecord=>{ result.push(createPerson(aRecord)); }); return result; } |
//두 함수 다듬기 function createPerson(aRecord){ switch (aRecord.gender){ case 'M' : return new Male(aRecord.name); case 'F' : return new Female(aRecord.name); default : return new Person(aRecord.name); } } //반복문 파이프라인으로 바꾸기 function loadFromInput(data){ return data.map(aRecord=>createPerson(aRecord)); } |
class Person{ constructor(name){ this._name = name; } //타입 검사 코드를 함수로 추출 get isMale(){return this instanceof Male;} get name(){return this._name;} get genderCode(){return "X";} } class Male extends Person{ get genderCode(){return "M";} } class Female extends Person{ get genderCode(){return "F";} } //클라이언트 //클라이언트에서 instanceof 연산자를 사용하는 것부터 구린내가 난다. const numberOfMales = people.filter(p=>p.isMale).length; |
class Person{ //생성자에 젠더코드 추가 constructor(name, genderCode){ this._name = name; this._genderCode = genderCode || "X"; } get isMale(){return this instanceof Male;} get name(){return this._name;} get genderCode(){return this._genderCode;} } |
function createPerson(aRecord){ switch (aRecord.gender){ //하나씩 서브클래스 제거 case 'M' : return new Person(aRecord.name, "M"); case 'F' : return new Female(aRecord.name); default : return new Person(aRecord.name); } } function loadFromInput(data){ return data.map(aRecord=>createPerson(aRecord)); } class Person{ //생성자에 젠더코드 추가 constructor(name, genderCode){ this._name = name; this._genderCode = genderCode || "X"; } get isMale(){return "M"=== this._genderCode;} get name(){return this._name;} get genderCode(){return this._genderCode;} } class Female extends Person{ get genderCode(){return "F";} } |
function createPerson(aRecord){ switch (aRecord.gender){ case 'M' : return new Person(aRecord.name, "M"); case 'F' : return new Person(aRecord.name, "F"); default : return new Person(aRecord.name, "X"); } } function loadFromInput(data){ return data.map(aRecord=>createPerson(aRecord)); } class Person{ constructor(name, genderCode){ this._name = name; this._genderCode = genderCode ; } get isMale(){return "M"=== this._genderCode;} get name(){return this._name;} get genderCode(){return this._genderCode;} } //클라이언트 const numberOfMales = people.filter(p=>p.isMale).length; |
'IT책, 강의 > 리팩터링' 카테고리의 다른 글
12 - 상속 다루기 - 계층 합치기 (0) | 2023.11.02 |
---|---|
12 - 상속 다루기 - 슈퍼클래스 추출하기 (1) | 2023.11.01 |
12 - 상속 다루기 - 타입 코드를 서브클래스로 바꾸기 (0) | 2023.10.30 |
12 - 상속 다루기 - 필드 내리기 (0) | 2023.10.29 |
12 - 상속 다루기 - 메서드 내리기 (0) | 2023.10.28 |