Design Pattern

Singleton pattern, 싱글톤 패턴

iKay 2020. 4. 2. 22:34
반응형

싱글톤 패턴이란

Singleton pattern(싱글톤 패턴)은 인스턴스가 오직 하나만 생성되고, 어디서든지 이 인스턴스에 접근할 수 있게 하는 디자인 패턴이다. 객체를 생성하는 과정 없이 static method인 getInstance로 인스턴스를 바로 사용한다.

 

스타크래프트의 SCV가 Mineral, Gas를 수집하고, 사용하는데 전역적으로 사용되는 객체인 자원 Mineral과 Gas는 Singleton pattern으로 표현될 수 있다. 이를 다음과 같이 표현할 수 있겠다.

 

클래스 다이어그램

Resource를 추상클래스로 두고 Mineral과 Gas는 상속 받는다. 메소드의 행위는 같고 자원의 속성 값(amount)만 다르기 때문이다.

 

코드

타입스크립트 코드로 나타내면 다음과 같다. Main 함수에서 보다시피, mineral, gas의 객체를 여러 번 생성해도 하나의 객체를 생성한 것 처럼 동작하는 것을 확인할 수 있다. static method인 getInstance를 통해 컴파일시 이미 생성된 객체를 사용하기 때문이다.

 

abstract class Resource {
    amount: number = 0;
    consumed(amount: number): void {
        this.amount -= amount;
    }
    collected(amount: number): void {
        this.amount += amount;
    }
    getAmount(): number {
        return this.amount;
    }
}

class Mineral extends Resource {
    private static mineral = new Mineral();
    private constructor() {
        super();
    }
    static getInstance() {
        return Mineral.mineral;
    }
}

class Gas extends Resource {
    private static gas = new Gas();
    private constructor() {
        super();
    }
    static getInstance() {
        return Gas.gas;
    }
}

class Scv {
    collect(resource: Resource, amount: number) {
        resource.collected(amount);
    }

    repair(
        mineral: Mineral,
        gas: Gas,
        consumedMineral: number,
        consumedGas: number,
    ) {
        mineral.consumed(consumedMineral);
        gas.consumed(consumedGas);
    }
}

function Main() {
    const mineral1 = Mineral.getInstance();
    const mineral2 = Mineral.getInstance();
    const mineral3 = Mineral.getInstance();
    const mineral4 = Mineral.getInstance();

    const gas1 = Gas.getInstance();
    const gas2 = Gas.getInstance();

    const scv1 = new Scv();
    const scv2 = new Scv();
    const scv3 = new Scv();
    const scv4 = new Scv();

    scv1.collect(mineral1, 8);
    scv2.collect(mineral2, 8);
    scv3.collect(mineral3, 8);
    scv4.collect(mineral4, 8);

    scv1.collect(gas1, 8);
    scv1.collect(gas2, 8);

    console.log(mineral1.getAmount()); // 32
    console.log(gas1.getAmount()); // 16

    console.log(mineral1 === mineral2); // true
    console.log(gas1 === gas2); // true
    console.log(mineral1 === gas1); // false

    scv1.repair(Mineral.getInstance(), Gas.getInstance(), 10, 5);

    console.log(mineral1.getAmount()); // 22
    console.log(gas1.getAmount()); // 11
}

 

결론

위 코드를 보면 알겠지만 Singleton 객체는 전역변수처럼 행동한다. 어디서든지 이 객체에 접근이 가능하고 사용할 수 있는 장점이 있으나, static을 사용하기 때문에 계속 메모리에 상주하게 되어 남용하게 되면 메모리 낭비를 초래할 수도 있게 된다. 또한 Javascript/Typescript 환경이라면 크게 상관 없겠으나, 다중 쓰레드가 지원하는 언어라면 쓰레드간 동기화도 고려해야 함을 명심하도록 한다.

반응형

'Design Pattern' 카테고리의 다른 글

Observer pattern, 옵저버 패턴  (0) 2020.05.18
State pattern, 스테이트 패턴  (0) 2020.04.28
Command Pattern, 커맨트 패턴  (0) 2020.04.13
Strategy pattern, 스트레이티지 패턴  (0) 2020.04.01