개요

서브클래싱은 원래 데이터 구조와 다른 변종 또는 종류에 따라 다르게 동작하게 있는 유용한 메커니즘이나, 이상 사용이 안된다면 제거하는 것이 최선

 

예시



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;

 

+ Recent posts