JS/[inflearn] TS JS 디자인패턴

SOLID 원칙

web_seul 2025. 1. 16. 14:23

SOLID 원칙

소프트웨어 작업에서 코드를 리팩터링하여 읽기 쉽고 확장하기 쉽게 적용하는 지침

 

두문자 약어 개념
S SRP 단일 책임 원칙 (Single responsibility principle) 
: 한 클래스는 하나의 책임만 가진다.
O OCP 개방/폐쇄 원칙 (Open/closed principle)
: 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.
L LSP 리스코프 치환 원칙 (Liskov substitution principle)
: 프로그램의 객체는 프로그램의 정확성을 깨지않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
I ISP 인터페이스 분리 원칙 (Interface segregation principle)
: 특정 클라이언트를 위한 인터페이스 여러개가 범용 인스턴스 하나보다 낫다.
D DIP 의존관계 역전 원칙 (Dependency inversion principle)
: 추상화에 의존해야지, 구체화에 의존하면 안된다.

 

1. SRP, 단일책임 원칙 : 객체는 단 하나의 책임(순서)만 가진다

응집도는 높게, 결합도는 낮게, 캡슐화가 가장 잘 발현됨, 

 

2. OCP, 개방폐쇄 원칙 : 기존 코드를 변경하지 않으면서 기능을 추가할 수 있도록

//d가 추가되면 else if가 추가되면서
//기존 코드를 수정해야함
function main(type){
    if(type === 'a'){
        doA();
    }else if(type === 'b'){
        doB();
    }else if(type === 'c'){
        doC();
    }else if(type === 'd'){
        doD();        
    }else{
        error;
    }
}
//d가 추가되어도 수정이 아닌 추가만으로 가능함
interface Doable {
    do(): void;
}
function main(type: Doable){
    type.do();
}
const a = {do(){}}
const b = {do(){}}
const c = {do(){}}
const d = {do(){}}

 

3. LSP, 리스코프치환 원칙 : 자식 클래스는 최소한 부모클래스에서 가능한 행위를 수행할 수 있어야 한다.

자식 클래스는 부모클래스를 대체할 수 있어야함

class Animal{
    isAnimal(){
        return true;
    }
}
class Bird extends Animal{
    fly(){
        return '파닥파닥';
    }
    isBird(){
        return true;
    }
}
class Penguin extends Bird{
    override fly(){
        throw new Error('못날아');  
        //type:never return
        //부모의 타입을 자식이 다르게 정의하면 위반됨
    }
}

console.log(new Animal().isAnimal()); //true
console.log(new Penguin().fly().at(1)); //error

 

4. ISP, 인터페이스분리 원칙 : 자신이 사용하지 않는 인터페이스는 구현하지 말아야함 (인터페이스의 단일 원칙)

interface IBird{    
    fly(): string;
    quack(): string;
    //필요이상의 속성을 가져서 활용되지 못함
    //분리할 필요가 있음
}
class Bird extends Animal implements IBird{
   //IBird에 fly가 있어서 불필요하지만 구현해야하는 문제
    fly(){	
        return '파닥파닥';
    }
    quack(){
        return '짹짹';
    }
    isBird(){
        return true;
    }
}
class Penguin extends Bird{
    fly(){
        throw new Error('못날아')
    }
}
//interface 메서드 분리해주기
interface Quackable{
  quack(): string;
}
interface Flyable{
  fly(): string;
}

class Bird extends Aninmal implents Quackable{
  ~~
}

///필요에 따라 다중 implements 가능
class Bird extends Aninmal implements Quackable, Flyable{
  ~~
}

 

5.DIP, 의존역전 원칙 : 추상성이 높은 클래스와 의존 관계를 맺어야 한다.

//강결합 상태
function main(){
  a.do();
}

//약결합 권장
function main(grimpan: Grimpan){
    grimpan.initialize();
}

main(Grimpan.getInstance())
main(IEGrimpan.getInstance())
main(ChromeGrimpan.getInstance())
//매개변수나 생성자로 외부 객체 받기
//외부객체의 타입은 interface, abstract class로 받기
interface IObj{}
class Obj implements IObj{}

class A{
    constructor(obj?: IObj){}
    setObj(obj: IObj){}
}
new A(new Obj())	//생성자 주입	
new A().setObj(new Obj())	//setter 주입

 

반응형