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

생성 패턴 (Creational Pattern) _ 싱글턴 (Singleton)

web_seul 2025. 1. 16. 14:25

싱글턴 (Singleton)

단 하나만 존재해야 할 때, 하나의 클래스가 단 하나의 인스턴스만 생성되도록  보장

ex) 다크모드

 

문제 예시

//class와 instance가 분리되어 있어서 상태관리가 어려움

let instance: Grimpan;

class Grimpan {
    constructor(canvas: HTMLElement | null){
        if (!canvas || !(canvas instanceof HTMLElement)){
            throw new Error('canvas 엘리먼트를 입력하세요.');
        }
    }
    initialize(){}
    initializeMenu(){}
}

new Grimpan(document.querySelector('#canvas'));

 

해결 방안 1. 인스턴스화 해서 export

class Grimpan{
    constructor(canvas: HTMLElement | null){
        if(!canvas || !(canvas instanceof HTMLCanvasElement)){
            throw new Error('canvas 엘리먼트 입력')
        }
    }
    initialize(){}
    initializeMenu(){}
}

export default new Grimpan(document.querySelector('canvas'));	//export 할때 Grimpan instance화
//g1, g2는 싱글턴
import g1 from './grimpan.js';	
import g2 from './grimpan.js';

console.log(g1 == g2);	//true

 

해결 방안 2. static 활용 (언어제한x)

class Grimpan{
    private static instance : Grimpan;  //하단 static과 통일
    constructor(canvas: HTMLElement | null){	
        if(!canvas || !(canvas instanceof HTMLCanvasElement)){
            throw new Error('canvas 엘리먼트 입력')
        }
    }
    initialize(){}
    initializeMenu(){}

    //1. 다르게 그림판 생성
    //2. 유일하다는 것을 보장
    //-> 단일책임 원칙 위반함
    static getInstance(){	//static을 두면 instance화 해서 활용가능
        if(!this.instance){
            this.instance = new Grimpan(document.querySelector('canvas'))
        }
        return this.instance;
    }
}
export default Grimpan;
import Grimpan from './grimpan.js';	

console.log(Grimpan.getInstance() === Grimpan.getInstance());	//true

 

=> 객체가 하나만 생성이 되어야 하고 외부(클라이언트)에서 객체에 접근할 수 있어야 함

 

장점 단점
객체가 하나만 생성됨을 보장 가능 private 이라 테스트가 어려움
  단일책임 원칙 위반 : 생성의 기능 + 하나임을 보장 으로 단일 책임이 아님
  강결합으로 테스트가 어려움
//main과 Grimpan이 강결합 됨
function main(){
    Grimpan.getInstance().initialize();
}
main();

//약결합 됨
function main(instance: any){
    instance().initialize();
}
main(Grimpan.getInstance());
main(Editor.getInstance());
main(MsPaint.getInstance());

 

반응형